rdSplatTools Reference Manual

Last Updated: 4th October 2026
Current Version: 1.00


rdSplatTools Subsystem

class UrdSplatToolsSubsystem{
	
	// Loads a baked mask asset from its asset path
	bool rdLoadBakedMaskAsset(const FString& assetPath);

	// Loads an existing baked mask asset
	bool rdSetBakedMaskAsset(UrdSplatBakedMaskAsset* asset);

	// Returns the currently active baked mask asset (can be null).
	UrdSplatBakedMaskAsset* rdGetActiveBakedMaskAsset() const { return activeAsset; }

	// Clears the active mask asset.
	void rdClearActiveBakedMaskAsset();

	// Loads a baked map set from the passed in manifest filename synchronously on game thread (0 radius=all tiles)
	bool rdLoadBakedMapSet(const FString& manifestAssetPath,float loadRadius=0.0f);

	// Loads a baked map set from the passed in manifest pointer synchronously on game thread (0 radius=all tiles)
	bool rdLoadBakedMapSetFromAsset(UrdSplatMapManifestAsset* manifest,float loadRadius=0.0f);

	// Loads the Baked Mask Asynchronously
	bool rdLoadBakedMaskAssetAsync(const FString& assetPath);

	// Loads the baked mask set from the passed in manifest file asynchronously (0 radius=all tiles)
	bool rdLoadBakedMapSetAsync(const FString& manifestAssetPath,float loadRadius=0.0f);

	// Loads the baked mask set from the passed in loaded pointer file asynchronously (0 radius=all tiles)
	bool rdLoadBakedMapSetFromAssetAsync(UrdSplatMapManifestAsset* manifest,float loadRadius=0.0f);

	// true while an asynchronous load is active
	bool rdIsLoadingBakedMap();

	// Fired when an asynchronous baked map load finishes.
	FrdSplatBakedMapLoaded rdOnBakedMapLoaded;

	// Manual streaming origin (world X/Y) - used while set instead of the player pawn's position, e.g. a camera, a trigger volume or editor tests. Cleared with rdClearSplatMapStreamingOrigin.
	void rdSetSplatMapStreamingOrigin(float x,float y);

	// Back to following the player pawn's position as the streaming origin.
	void rdClearSplatMapStreamingOrigin();

	// Re-evaluate the streaming set immediately (it otherwise refreshes every 0.25 seconds) - call after a teleport or rapid travel.
	void rdUpdateSplatMapStreaming();

	// The active map set manifest, or null when a single map asset is active (or nothing is loaded).
	UrdSplatMapManifestAsset* rdGetActiveMapManifest();

	// returns the baked mask asset at x,y
	const UrdSplatBakedMaskAsset* resolveAssetAt(float x,float y) const;

	// Number of tiles of the active map set currently held in memory.
	int32 rdGetLoadedTileCount() const;

	// System memory of the held tiles (deep walk), or of the single active map when no set is streaming.
	int64 rdGetLoadedTilesMemoryBytes() const;

	// Fills 'values' with the value of every mask at the given world x/y, plus directions with the uphill direction of every mask's local gradient - Sobel-weighted over the surrounding texels.
	bool rdGetMaskValuesAt(float x,float y,TArray<float>& values,TArray<float>& directions);

	// Get the uphill direction (yaw degrees 0-360, 0=+X, 90=+Y) of each layers local gradient, Sobel-weighted over the surrounding 3x3 texel ring
	TArray<float> rdGetMaskDirectionsAt(float x,float y,bool& changed) const;

	// Get the uphill direction (yaw degrees 0-360, 0=+X, 90=+Y) of each layers local gradient plus that gradient's strength
	bool rdGetMaskGradientsAt(float x,float y,TArray<float>& angles,TArray<float>& strengths) const;

	// Value of one mask at the given world x/y.
	float rdGetMaskValue(int32 index,float x,float y,bool& changed) const;

	// Look up the value of one mask at a world X/Y location, bilinearly filtered across the surrounding texels.
	float rdGetMaskValueSmooth(int32 index,float x,float y,bool& changed) const;

	// Direction of one mask at the given world x/y.
	float rdGetMaskDirection(int32 index,float x,float y,bool& changed) const;

	// Value and Direction of one mask at the given world x/y.
	bool rdGetMaskValueAndDirection(int32 index,float x,float y,float& value,float& direction) const;
	
	// Advance StepDistance world units along the painted path of one mask while holding the falloff at TargetValue
	bool rdStepAlongMaskContour(int32 index,float x,float y,float targetValue,float stepDistance,float headingYaw,float& outX,float& outY,float& outHeadingYaw,float& outValue,float& outValueError) const;

	// Name of the active mask set (empty if none loaded).
	FString rdGetActiveMaskName() const;

	// "How inside a structure" the location is (0-1)
	float rdUpdateInteriorness(const FVector& probeLocation);

	// The last smoothed interiorness and room-size estimate without recalculating
	float rdGetInteriorness(float& outRoomSize) const { outRoomSize=roomSizeValue; return interiornessValue; }

protected:

	TObjectPtr<UrdSplatBakedMaskAsset> activeAsset;
	
	// Per-mask heading steered by rdGetMaskGradientsAt (yaw degrees, -1 = uninitialized).
	mutable TArray<float> lastGradientAngles;

	virtual void	Deinitialize() override;
	
	void			updateSplatMapStreaming(bool bBlocking);
	void			updateSplatMapStreamingTimer();
	bool			initBakedMapSet(UrdSplatMapManifestAsset* manifest,float loadRadius,bool bBlockingInitialTiles);
	void			onTileLoaded(int32 tileIndex,FSoftObjectPath assetPath);
	void			onAsyncBakedMaskAssetLoaded(FString assetPath);
	void			onAsyncManifestLoaded(FString manifestAssetPath,float loadRadius);
	bool			getStreamingOrigin(float& outX,float& outY) const;
	void			releaseBakedMapSet();

	void			logTileMemoryStats(int32 tileIndex) const;
};


rdSplatBakedMaskAsset

class UrdSplatBakedMaskAsset {
	
	// User-defined name for this baked mask set.
	FString name;

	// World-space origin (min corner) of the map.
	FVector landscapeMin=FVector::ZeroVector;

	// World-space extent of the map.
	float landscapeWidth=0.0f;

	float landscapeDepth=0.0f;

	// Map dimensions in texels (square RTs, so width==height).
	int32 resolution=0;

	// Per-mask metadata (parallel to the Masks array in every row).
	TArray<FString> maskNames;

	// Per-mask tint colours
	TArray<FLinearColor> maskColors;

	// The baked map: Map[row].Masks[mask] = RLE data of that mask in that row.
	TArray<FrdSplatRLERow> map;

	// Look up the value of one mask at a world X/Y location. Returns 0 if the location is outside the map or the index is invalid.
	float rdGetMaskValue(int32 index,float x,float y) const;

	// Look up the value of one mask at a world X/Y location, bilinearly filtered across the surrounding texels. Returns 0 if the location is outside the splatmap or the index is invalid.
	float rdGetMaskValueSmooth(int32 index,float x,float y) const;

	// Look up the direction of one mask at a world X/Y location.
	float rdGetMaskDirection(int32 index,float x,float y) const;

	// Look up the value and direction of one mask at a world X/Y location. Returns 0 if the location is outside the map or the index is invalid.
	bool rdGetMaskValueAndDirection(int32 index,float x,float y,float& value,float& direction) const;
	
	// Look up all mask values at a world X/Y location. Fills 'values' with one entry per mask (in the same order as MaskNames). Returns false if the location is outside the splatmap.
	bool rdGetMaskValuesAt(float x,float y,TArray<float>& values) const;

	// Get the uphill direction (yaw degrees 0-360, 0=+X, 90=+Y) of each layers local gradient, Sobel-weighted over the surrounding 3x3 texel ring
	bool rdGetMaskDirectionsAt(float x,float y,TArray<float>& directions) const;

	// Get the uphill direction (yaw degrees 0-360, 0=+X, 90=+Y) of each layers local gradient plus that gradient's strength
	bool rdGetMaskGradientsAt(float x,float y,TArray<float>& angles,TArray<float>& strengths) const;

	// Advance StepDistance world units along the painted path while holding the falloff at TargetValue.
	bool rdStepAlongMaskContour(int32 MaskIndex, float X, float Y, float TargetValue, float StepDistance, float HeadingYaw, float& OutX, float& OutY, float& OutHeadingYaw, float& OutValue, float& OutValueError) const;

	// Expand one mask's RLE data into a plain float image (Resolution * Resolution floats, row-major). Returns false on invalid index.
	bool rdDecodeMask(int32 index,TArray<float>& values) const;

	// Number of masks stored in this asset.
	int32 rdGetNumMasks() const { return maskNames.Num(); }

	// System memory this asset occupies while loaded: the object itself plus every container allocation in the RLE map tree,
	int64 rdGetSystemMemoryBytes() const;

	// Full memory breakdown of the loaded asset
	bool rdGetMemoryStats(FrdSplatMaskMemoryStats& stats,bool bMeasureTrueFootprint=true) const;

protected:
	bool worldToTexelInternal(float x,float y,float& outFx,float& outFy) const;
	float readTexelInternal(int32 maskIndex,int32 ix,int32 iy) const;
	float sampleTexelBilinearInternal(int32 maskIndex,float fx,float fy) const;
	float sampleWorldBilinearInternal(int32 maskIndex,float x,float y) const;
	void gradientWorldInternal(int32 maskIndex,float x,float y,float& outGx,float& outGy) const;

	// Walk the RLE map tree and fill the stats' deep-walk fields
	void accumulateDeepMemoryStatsInternal(FrdSplatMaskMemoryStats& outStats,bool bMeasureTrueFootprint) const;
};