UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
GridInterpolant.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3// Port of geometry3Sharp's CachingMeshSDFImplicit
4
5#pragma once
6
7#include "BoxTypes.h"
8#include "MathUtil.h"
9#include "VectorTypes.h"
10#include "IntVectorTypes.h"
11
12#include <type_traits>
13
14namespace UE
15{
16namespace Geometry
17{
18
19
27template <class GridType, typename RealType = double, bool bScalarCellSize = true>
28class TTriLinearGridInterpolant /*: public BoundedImplicitFunction3d (TODO: consider add ImplicitFunction3d interface concept once more implicit functions are available*/
29{
30
31public:
32
33 // Type to use for CellSize
34 using CellSizeType = std::conditional_t<bScalarCellSize, RealType, TVector<RealType>>;
35
40
41 // value to return if query point is outside Grid (in an SDF
42 // outside is usually positive). Need to do math with this value,
43 // and cast this value to/from float; use TMathUtil<RealType>::SafeLargeValue to avoid overflow
45
49
51 {
54 { GridOrigin.X + GetDim(CellSize, 0) * (Dimensions.X - 1),
55 GridOrigin.Y + GetDim(CellSize, 1) * (Dimensions.Y - 1),
56 GridOrigin.Z + GetDim(CellSize, 2) * (Dimensions.Z - 1)});
57 }
58
60 {
61 // compute integer coordinates
63 CellCoords.X = (int)((Pt.X - GridOrigin.X) / GetDim(CellSize, 0));
64 CellCoords.Y = (int)((Pt.Y - GridOrigin.Y) / GetDim(CellSize, 1));
65 CellCoords.Z = (int)((Pt.Z - GridOrigin.Z) / GetDim(CellSize, 2));
66
67 return CellCoords;
68 }
69
70 template<bool bClamped = false>
71 RealType Value(const TVector<RealType>& Pt) const
72 {
74 ((Pt.X - GridOrigin.X) / GetDim(CellSize, 0)),
75 ((Pt.Y - GridOrigin.Y) / GetDim(CellSize, 1)),
76 ((Pt.Z - GridOrigin.Z) / GetDim(CellSize, 2)));
77
78 if constexpr (bClamped)
79 {
80 gridPt.X = FMath::Clamp(gridPt.X, 0, Dimensions.X - (1 + FMathd::Epsilon));
81 gridPt.Y = FMath::Clamp(gridPt.Y, 0, Dimensions.Y - (1 + FMathd::Epsilon));
82 gridPt.Z = FMath::Clamp(gridPt.Z, 0, Dimensions.Z - (1 + FMathd::Epsilon));
83 }
84
85 // compute integer coordinates
86 int X0 = (int)gridPt.X;
87 int Y0 = (int)gridPt.Y, Y1 = Y0 + 1;
88 int Z0 = (int)gridPt.Z, Z1 = Z0 + 1;
89
90 // return Outside if not in Grid
91 if constexpr (!bClamped)
92 {
93 if (X0 < 0 || (X0 + 1) >= Dimensions.X ||
96 {
97 return Outside;
98 }
99 }
100
101 // convert double coords to [0,1] range
102 RealType fAx = gridPt.X - (RealType)X0;
103 RealType fAy = gridPt.Y - (RealType)Y0;
104 RealType fAz = gridPt.Z - (RealType)Z0;
105 RealType OneMinusfAx = (RealType)(1.0) - fAx;
106
107 // compute trilinear interpolant. The code below tries to do this with the fewest
108 // number of variables, in hopes that optimizer will be clever about re-using registers, etc.
109 // Commented code at bottom is fully-expanded version.
110 RealType xa, xb;
111
112 get_value_pair(X0, Y0, Z0, xa, xb);
113 RealType yz = (1 - fAy) * (1 - fAz);
114 RealType sum = (OneMinusfAx * xa + fAx * xb) * yz;
115
116 get_value_pair(X0, Y0, Z1, xa, xb);
117 yz = (1 - fAy) * (fAz);
118 sum += (OneMinusfAx * xa + fAx * xb) * yz;
119
120 get_value_pair(X0, Y1, Z0, xa, xb);
121 yz = (fAy) * (1 - fAz);
122 sum += (OneMinusfAx * xa + fAx * xb) * yz;
123
124 get_value_pair(X0, Y1, Z1, xa, xb);
125 yz = (fAy) * (fAz);
126 sum += (OneMinusfAx * xa + fAx * xb) * yz;
127
128 return sum;
129
130 // fV### is Grid cell corner index
131 //return
132 // fV000 * (1 - fAx) * (1 - fAy) * (1 - fAz) +
133 // fV001 * (1 - fAx) * (1 - fAy) * (fAz) +
134 // fV010 * (1 - fAx) * (fAy) * (1 - fAz) +
135 // fV011 * (1 - fAx) * (fAy) * (fAz) +
136 // fV100 * (fAx) * (1 - fAy) * (1 - fAz) +
137 // fV101 * (fAx) * (1 - fAy) * (fAz) +
138 // fV110 * (fAx) * (fAy) * (1 - fAz) +
139 // fV111 * (fAx) * (fAy) * (fAz);
140 }
141
142
143protected:
144 void get_value_pair(int I, int J, int K, RealType& A, RealType& B) const
145 {
146 A = (RealType)Grid->GetValue(FVector3i(I, J, K));
147 B = (RealType)Grid->GetValue(FVector3i(I + 1, J, K));
148 }
149
150
151public:
153 {
155 ((Pt.X - GridOrigin.X) / GetDim(CellSize, 0)),
156 ((Pt.Y - GridOrigin.Y) / GetDim(CellSize, 1)),
157 ((Pt.Z - GridOrigin.Z) / GetDim(CellSize, 2)));
158
159 // clamp to Grid
160 if (gridPt.X < 0 || gridPt.X >= Dimensions.X - 1 ||
161 gridPt.Y < 0 || gridPt.Y >= Dimensions.Y - 1 ||
162 gridPt.Z < 0 || gridPt.Z >= Dimensions.Z - 1)
163 {
165 }
166
167 // compute integer coordinates
168 int X0 = (int)gridPt.X;
169 int Y0 = (int)gridPt.Y, Y1 = Y0 + 1;
170 int Z0 = (int)gridPt.Z, Z1 = Z0 + 1;
171
172 // convert RealType coords to [0,1] range
173 RealType fAx = gridPt.X - (RealType)X0;
174 RealType fAy = gridPt.Y - (RealType)Y0;
175 RealType fAz = gridPt.Z - (RealType)Z0;
176
177 RealType fV000, fV100;
179 RealType fV010, fV110;
181 RealType fV001, fV101;
183 RealType fV011, fV111;
184 get_value_pair(X0, Y1, Z1, fV011, fV111);
185
186 // [TODO] can re-order this to vastly reduce number of ops!
187 RealType gradX =
188 -fV000 * (1 - fAy) * (1 - fAz) +
189 -fV001 * (1 - fAy) * (fAz)+
190 -fV010 * (fAy) * (1 - fAz) +
191 -fV011 * (fAy) * (fAz)+
192 fV100 * (1 - fAy) * (1 - fAz) +
193 fV101 * (1 - fAy) * (fAz)+
194 fV110 * (fAy) * (1 - fAz) +
195 fV111 * (fAy) * (fAz);
196
197 RealType gradY =
198 -fV000 * (1 - fAx) * (1 - fAz) +
199 -fV001 * (1 - fAx) * (fAz)+
200 fV010 * (1 - fAx) * (1 - fAz) +
201 fV011 * (1 - fAx) * (fAz)+
202 -fV100 * (fAx) * (1 - fAz) +
203 -fV101 * (fAx) * (fAz)+
204 fV110 * (fAx) * (1 - fAz) +
205 fV111 * (fAx) * (fAz);
206
207 RealType gradZ =
208 -fV000 * (1 - fAx) * (1 - fAy) +
209 fV001 * (1 - fAx) * (1 - fAy) +
210 -fV010 * (1 - fAx) * (fAy)+
211 fV011 * (1 - fAx) * (fAy)+
212 -fV100 * (fAx) * (1 - fAy) +
213 fV101 * (fAx) * (1 - fAy) +
214 -fV110 * (fAx) * (fAy)+
215 fV111 * (fAx) * (fAy);
216
218 }
219
220private:
221 inline static RealType GetDim(CellSizeType CellSize, int32 Axis)
222 {
223 if constexpr (bScalarCellSize)
224 {
225 return CellSize;
226 }
227 else
228 {
229 return CellSize[Axis];
230 }
231 }
232};
233
234
235} // end namespace UE::Geometry
236} // end namespace UE
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
Definition MathUtil.h:150
Definition GridInterpolant.h:29
FVector3i Dimensions
Definition GridInterpolant.h:39
GridType * Grid
Definition GridInterpolant.h:36
RealType Outside
Definition GridInterpolant.h:44
void get_value_pair(int I, int J, int K, RealType &A, RealType &B) const
Definition GridInterpolant.h:144
TAxisAlignedBox3< RealType > Bounds() const
Definition GridInterpolant.h:50
TVector< RealType > Gradient(const TVector< RealType > &Pt) const
Definition GridInterpolant.h:152
FVector3i Cell(const TVector< RealType > &Pt) const
Definition GridInterpolant.h:59
std::conditional_t< bScalarCellSize, RealType, TVector< RealType > > CellSizeType
Definition GridInterpolant.h:34
TTriLinearGridInterpolant(GridType *Grid, TVector< RealType > GridOrigin, CellSizeType CellSize, FVector3i Dimensions)
Definition GridInterpolant.h:46
RealType Value(const TVector< RealType > &Pt) const
Definition GridInterpolant.h:71
CellSizeType CellSize
Definition GridInterpolant.h:38
TVector< RealType > GridOrigin
Definition GridInterpolant.h:37
Definition AdvancedWidgetsModule.cpp:13
static constexpr UE_FORCEINLINE_HINT T Clamp(const T X, const T MinValue, const T MaxValue)
Definition UnrealMathUtility.h:592
Definition IntVectorTypes.h:252
int32 Z
Definition IntVectorTypes.h:257
int32 X
Definition IntVectorTypes.h:257
int32 Y
Definition IntVectorTypes.h:257
Definition BoxTypes.h:247
Definition Vector.h:51
T Z
Definition Vector.h:68
static TVector< T > Zero()
Definition Vector.h:112
T Y
Definition Vector.h:65
T X
Definition Vector.h:62