Jolt Physics
A multi core friendly Game Physics Engine
Loading...
Searching...
No Matches
HairSettings.h
Go to the documentation of this file.
1// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
14
16
17class StreamOut;
18class StreamIn;
19
21class JPH_EXPORT HairSettings : public RefTarget<HairSettings>
22{
24
25public:
27 struct JPH_EXPORT SkinWeight : public JPH_HairSkinWeight
28 {
30 };
31
33 struct JPH_EXPORT SkinPoint : public JPH_HairSkinPoint
34 {
36 };
37
38 static constexpr uint32 cNoInfluence = ~uint32(0);
39
41 struct JPH_EXPORT SVertexInfluence : public JPH_HairSVertexInfluence
42 {
44
45 inline SVertexInfluence() { mVertexIndex = cNoInfluence; mRelativePosition = JPH_float3(0, 0, 0); mWeight = 0.0f; }
46 };
47
56
59 {
61
62
63 SVertex() = default;
64 explicit SVertex(const Float3 &inPosition, float inInvMass = 1.0f) : mPosition(inPosition), mInvMass(inInvMass) { }
65
66 Float3 mPosition { 0, 0, 0 };
67 float mInvMass = 1.0f;
68 float mLength = 0.0f;
69 float mStrandFraction = 0.0f;
70 Float4 mBishop { 0, 0, 0, 1.0f };
71 Float4 mOmega0 { 0, 0, 0, 1.0f };
72 };
73
76 {
78
79
80 RStrand() = default;
81 RStrand(uint32 inStartVtx, uint32 inEndVtx) : mStartVtx(inStartVtx), mEndVtx(inEndVtx) { }
82
83 uint32 VertexCount() const { return mEndVtx - mStartVtx; }
84
85 float MeasureLength(const Array<SVertex> &inVertices) const
86 {
87 float length = 0.0f;
88 for (uint32 v = mStartVtx; v < mEndVtx - 1; ++v)
89 length += (Vec3(inVertices[v + 1].mPosition) - Vec3(inVertices[v].mPosition)).Length();
90 return length;
91 }
92
95 };
96
98 struct JPH_EXPORT SStrand : public RStrand
99 {
101
102 SStrand() = default;
103 SStrand(uint32 inStartVtx, uint32 inEndVtx, uint32 inMaterialIndex) : RStrand(inStartVtx, inEndVtx), mMaterialIndex(inMaterialIndex) { }
104
106 };
107
110 {
112
113 public:
114 Gradient() = default;
115 Gradient(float inMin, float inMax, float inMinFraction = 0.0f, float inMaxFraction = 1.0f) : mMin(inMin), mMax(inMax), mMinFraction(inMinFraction), mMaxFraction(inMaxFraction) { }
116
128 Gradient MakeStepDependent(float inTimeRatio) const
129 {
130 auto make_dependent = [inTimeRatio](float inValue) {
131 return 1.0f - std::pow(1.0f - inValue, inTimeRatio);
132 };
133
134 return Gradient(make_dependent(mMin), make_dependent(mMax), mMinFraction, mMaxFraction);
135 }
136
138 void SaveBinaryState(StreamOut &inStream) const;
139
141 void RestoreBinaryState(StreamIn &inStream);
142
143 float mMin = 0.0f;
144 float mMax = 1.0f;
145 float mMinFraction = 0.0f;
146 float mMaxFraction = 1.0f;
147 };
148
150 {
151 public:
152 GradientSampler() = default;
153
154 explicit GradientSampler(const Gradient &inGradient) :
155 mMultiplier((inGradient.mMax - inGradient.mMin) / (inGradient.mMaxFraction - inGradient.mMinFraction)),
156 mOffset(inGradient.mMin - inGradient.mMinFraction * mMultiplier),
157 mMin(min(inGradient.mMin, inGradient.mMax)),
158 mMax(max(inGradient.mMin, inGradient.mMax))
159 {
160 }
161
163 inline float Sample(float inFraction) const
164 {
165 return min(mMax, max(mMin, mOffset + inFraction * mMultiplier));
166 }
167
168 inline float Sample(const SStrand &inStrand, uint32 inVertex) const
169 {
170 return Sample(float(inVertex - inStrand.mStartVtx) / float(inStrand.VertexCount() - 1));
171 }
172
174 inline Float4 ToFloat4() const
175 {
176 return Float4(mMultiplier, mOffset, mMin, mMax);
177 }
178
179 private:
180 float mMultiplier;
181 float mOffset;
182 float mMin;
183 float mMax;
184 };
185
188 {
190
191
192 bool NeedsGrid() const { return mGridVelocityFactor.mMin != 0.0f || mGridVelocityFactor.mMax != 0.0f || mGridDensityForceFactor != 0.0f; }
193
195 bool GlobalPoseOnly() const { return !mEnableCollision && mGlobalPose.mMin == 1.0f && mGlobalPose.mMax == 1.0f; }
196
198 float GetBendCompliance(float inStrandFraction) const
199 {
200 float fraction = inStrandFraction * 3.0f;
201 uint idx = min(uint(fraction), 2u);
202 fraction = fraction - float(idx);
203 JPH_ASSERT(fraction >= 0.0f && fraction <= 1.0f);
204 float multiplier = mBendComplianceMultiplier[idx] * (1.0f - fraction) + mBendComplianceMultiplier[idx + 1] * fraction;
205 return multiplier * mBendCompliance;
206 }
207
208 bool mEnableCollision = true;
209 bool mEnableLRA = true;
210 float mLinearDamping = 2.0f;
211 float mAngularDamping = 2.0f;
212 float mMaxLinearVelocity = 10.0f;
213 float mMaxAngularVelocity = 50.0f;
214 Gradient mGravityFactor { 0.1f, 1.0f, 0.2f, 0.8f };
215 float mFriction = 0.2f;
216 float mBendCompliance = 1.0e-7f;
217 Float4 mBendComplianceMultiplier = { 1.0f, 100.0f, 100.0f, 1.0f };
218 float mStretchCompliance = 1.0e-8f;
219 float mInertiaMultiplier = 10.0f;
220 Gradient mHairRadius = { 0.001f, 0.001f };
222 Gradient mGridVelocityFactor { 0.05f, 0.01f };
224 Gradient mGlobalPose { 0.01f, 0, 0.0f, 0.3f };
225 Gradient mSkinGlobalPose { 1.0f, 0.0f, 0.0f, 0.1f };
228 };
229
234 void InitRenderAndSimulationStrands(const Array<SVertex> &inVertices, const Array<SStrand> &inStrands);
235
237 static void sResample(Array<SVertex> &ioVertices, Array<SStrand> &ioStrands, uint32 inNumVerticesPerStrand);
238
241 void Init(float &outMaxDistSqHairToScalp);
242
244 void InitCompute(ComputeSystem *inComputeSystem);
245
247 float GetNeutralDensity(uint32 inX, uint32 inY, uint32 inZ) const
248 {
249 JPH_ASSERT(inX < mGridSize.GetX() && inY < mGridSize.GetY() && inZ < mGridSize.GetZ());
250 return mNeutralDensity[inX + inY * mGridSize.GetX() + inZ * mGridSize.GetX() * mGridSize.GetY()];
251 }
252
255 {
257 }
258
263 void PrepareForScalpSkinning(Mat44Arg inJointToHair, const Mat44 *inJointMatrices, Mat44 *outJointMatrices) const;
264
269 void SkinScalpVertices(Mat44Arg inJointToHair, const Mat44 *inJointMatrices, Array<Vec3> &outVertices) const;
270
272 void SaveBinaryState(StreamOut &inStream) const;
273
275 void RestoreBinaryState(StreamIn &inStream);
276
278 {
279 public:
280 inline explicit GridSampler(const HairSettings *inSettings) :
281 mGridSizeMin2(inSettings->mGridSize - UVec4::sReplicate(2)),
282 mGridSizeMin1((inSettings->mGridSize - UVec4::sReplicate(1)).ToFloat()),
283 mGridStride(1, inSettings->mGridSize.GetX(), inSettings->mGridSize.GetX() * inSettings->mGridSize.GetY(), 0),
284 mOffset(inSettings->mSimulationBounds.mMin),
285 mScale(Vec3(inSettings->mGridSize.ToFloat()) / inSettings->mSimulationBounds.GetSize())
286 {
287 }
288
290 inline void PositionToIndexAndFraction(Vec3Arg inPosition, UVec4 &outIndex, Vec3 &outFraction) const
291 {
292 // Get position in grid space
293 Vec3 grid_pos = Vec3::sMin(Vec3::sMax(inPosition - mOffset, Vec3::sZero()) * mScale, mGridSizeMin1);
294 outIndex = UVec4::sMin(Vec4(grid_pos).ToInt(), mGridSizeMin2);
295 outFraction = grid_pos - Vec3(outIndex.ToFloat());
296 }
297
298 template <typename F>
299 inline void Sample(UVec4Arg inIndex, Vec3Arg inFraction, const F &inFunc) const
300 {
301 Vec3 fraction[] = { Vec3::sReplicate(1.0f) - inFraction, inFraction };
302
303 // Sample the grid
304 for (uint32 z = 0; z < 2; ++z)
305 for (uint32 y = 0; y < 2; ++y)
306 for (uint32 x = 0; x < 2; ++x)
307 {
308 uint32 index = mGridStride.Dot(inIndex + UVec4(x, y, z, 0));
309 float combined_fraction = fraction[x].GetX() * fraction[y].GetY() * fraction[z].GetZ();
310 inFunc(index, combined_fraction);
311 }
312 }
313
314 template <typename F>
315 inline void Sample(Vec3Arg inPosition, const F &inFunc) const
316 {
317 UVec4 index;
318 Vec3 fraction;
319 PositionToIndexAndFraction(inPosition, index, fraction);
320 Sample(index, fraction, inFunc);
321 }
322
328 };
329
330 static constexpr uint32 cDefaultIterationsPerSecond = 360;
331
334
337
343
345 float mMaxDeltaTime = 1.0f / 30.0f;
346 UVec4 mGridSize { 32, 32, 32, 0 };
348 Vec3 mInitialGravity { 0, -9.81f, 0 };
350
351 // Values computed by Init
355 float mDensityScale = 0.0f;
357
358 // Compute data
373};
374
#define JPH_EXPORT
Definition Core.h:286
unsigned int uint
Definition Core.h:546
#define JPH_NAMESPACE_END
Definition Core.h:469
std::uint32_t uint32
Definition Core.h:549
#define JPH_NAMESPACE_BEGIN
Definition Core.h:463
#define JPH_ASSERT(...)
Definition IssueReporting.h:33
const Vec3 Vec3Arg
Definition MathTypes.h:19
const Mat44 & Mat44Arg
Definition MathTypes.h:29
const UVec4 UVec4Arg
Definition MathTypes.h:26
#define JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(linkage, class_name)
Definition SerializableObject.h:80
float3 JPH_float3
Definition ShaderCore.h:42
Axis aligned box.
Definition AABox.h:16
Definition Array.h:36
Interface to run a workload on the GPU.
Definition ComputeSystem.h:16
Class that holds 3 floats. Used as a storage class. Convert to Vec3 for calculations.
Definition Float3.h:13
Class that holds 4 float values. Convert to Vec4 to perform calculations.
Definition Float4.h:11
Gradient along a hair strand of a value, e.g. compliance, friction, etc.
Definition HairSettings.h:110
Gradient MakeStepDependent(float inTimeRatio) const
Definition HairSettings.h:128
float mMin
Minimum value of the gradient.
Definition HairSettings.h:143
float mMax
Maximum value of the gradient.
Definition HairSettings.h:144
float mMaxFraction
Fraction along the hair strand that corresponds to the maximum value.
Definition HairSettings.h:146
Gradient(float inMin, float inMax, float inMinFraction=0.0f, float inMaxFraction=1.0f)
Definition HairSettings.h:115
float mMinFraction
Fraction along the hair strand that corresponds to the minimum value.
Definition HairSettings.h:145
float Sample(const SStrand &inStrand, uint32 inVertex) const
Definition HairSettings.h:168
GradientSampler(const Gradient &inGradient)
Definition HairSettings.h:154
Float4 ToFloat4() const
Convert to Float4 to pass to shader.
Definition HairSettings.h:174
float Sample(float inFraction) const
Sample the value along the strand.
Definition HairSettings.h:163
Vec3 mGridSizeMin1
Definition HairSettings.h:324
UVec4 mGridSizeMin2
Definition HairSettings.h:323
void Sample(UVec4Arg inIndex, Vec3Arg inFraction, const F &inFunc) const
Definition HairSettings.h:299
GridSampler(const HairSettings *inSettings)
Definition HairSettings.h:280
Vec3 mScale
Definition HairSettings.h:327
void PositionToIndexAndFraction(Vec3Arg inPosition, UVec4 &outIndex, Vec3 &outFraction) const
Convert a position in hair space to a grid index and fraction.
Definition HairSettings.h:290
UVec4 mGridStride
Definition HairSettings.h:325
void Sample(Vec3Arg inPosition, const F &inFunc) const
Definition HairSettings.h:315
Vec3 mOffset
Definition HairSettings.h:326
This class defines the setup of a hair groom, it can be shared between multiple hair instances.
Definition HairSettings.h:22
Array< SVertex > mSimVertices
Simulated vertices. Used by mSimStrands.
Definition HairSettings.h:332
Array< SStrand > mSimStrands
Defines the start and end of each simulated strand.
Definition HairSettings.h:333
void RestoreBinaryState(StreamIn &inStream)
Restore the state of this object from inStream.
Definition HairSettings.cpp:800
Array< SkinWeight > mScalpSkinWeights
Skin weights of the scalp mesh, for each vertex we have mScalpNumSkinWeightsPerVertex entries.
Definition HairSettings.h:341
Ref< ComputeBuffer > mVerticesBishopCB
Definition HairSettings.h:365
Array< SkinPoint > mSkinPoints
For each simulated vertex, where it is attached to the scalp mesh.
Definition HairSettings.h:352
Ref< ComputeBuffer > mScalpSkinWeightsCB
Definition HairSettings.h:361
Ref< ComputeBuffer > mVerticesLengthCB
Definition HairSettings.h:367
Ref< ComputeBuffer > mVerticesOmega0CB
Definition HairSettings.h:366
Ref< ComputeBuffer > mScalpVerticesCB
Definition HairSettings.h:359
uint mScalpNumSkinWeightsPerVertex
Number of skin weights per vertex.
Definition HairSettings.h:342
Vec3 mInitialGravity
Initial gravity in local space of the hair, used to calculate the unloaded rest pose.
Definition HairSettings.h:348
Ref< ComputeBuffer > mVerticesStrandFractionCB
Definition HairSettings.h:368
void InitCompute(ComputeSystem *inComputeSystem)
Must be called after Init to setup the compute buffers.
Definition HairSettings.cpp:644
void Init(float &outMaxDistSqHairToScalp)
Definition HairSettings.cpp:370
Array< float > mNeutralDensity
Neutral density grid used to apply forces to keep the hair in place.
Definition HairSettings.h:354
Vec3 mSimulationBoundsPadding
Padding around the simulation bounds to ensure that the grid is large enough and that we detect colli...
Definition HairSettings.h:347
Array< Mat44 > mScalpInverseBindPose
Inverse bind pose of the scalp mesh, joints are in model space.
Definition HairSettings.h:340
float GetNeutralDensity(uint32 inX, uint32 inY, uint32 inZ) const
Sample the neutral density at a grid position.
Definition HairSettings.h:247
Ref< ComputeBuffer > mScalpTrianglesCB
Definition HairSettings.h:360
Array< RStrand > mRenderStrands
Defines the start and end of each rendered strand.
Definition HairSettings.h:336
Array< Material > mMaterials
Materials used by the hair strands.
Definition HairSettings.h:349
Ref< ComputeBuffer > mSkinPointsCB
Definition HairSettings.h:362
Ref< ComputeBuffer > mStrandVertexCountsCB
Definition HairSettings.h:369
Ref< ComputeBuffer > mVerticesPositionCB
Definition HairSettings.h:364
static void sResample(Array< SVertex > &ioVertices, Array< SStrand > &ioStrands, uint32 inNumVerticesPerStrand)
Resample the hairs to a new fixed number of vertices per strand. Must be called prior to Init if desi...
Definition HairSettings.cpp:267
Array< RVertex > mRenderVertices
Rendered vertices. Used by mRenderStrands.
Definition HairSettings.h:335
Ref< ComputeBuffer > mVerticesFixedCB
Definition HairSettings.h:363
uint32 mMaxVerticesPerStrand
Maximum number of vertices per strand, used for padding the compute buffers.
Definition HairSettings.h:356
Ref< ComputeBuffer > mSVertexInfluencesCB
Definition HairSettings.h:372
Ref< ComputeBuffer > mStrandMaterialIndexCB
Definition HairSettings.h:370
void InitRenderAndSimulationStrands(const Array< SVertex > &inVertices, const Array< SStrand > &inStrands)
Definition HairSettings.cpp:130
float mDensityScale
Highest density value in the neutral density grid, used to scale the density for rendering.
Definition HairSettings.h:355
float mMaxDeltaTime
Maximum delta time for the simulation step (to avoid running an excessively long step,...
Definition HairSettings.h:345
static constexpr uint32 cNoInfluence
Definition HairSettings.h:38
Array< Float3 > mScalpVertices
Vertices of the scalp mesh, used to attach hairs. Note that the hair vertices mSimVertices must be in...
Definition HairSettings.h:338
Array< IndexedTriangleNoMaterial > mScalpTriangles
Triangles of the scalp mesh.
Definition HairSettings.h:339
static constexpr uint32 cDefaultIterationsPerSecond
Definition HairSettings.h:330
Ref< ComputeBuffer > mNeutralDensityCB
Definition HairSettings.h:371
UVec4 mGridSize
Number of grid cells used to simulate the hair. W unused.
Definition HairSettings.h:346
AABox mSimulationBounds
Bounds that the simulation is supposed to fit in.
Definition HairSettings.h:353
void SaveBinaryState(StreamOut &inStream) const
Saves the state of this object in binary form to inStream. Doesn't store the compute buffers.
Definition HairSettings.cpp:755
uint32 GetNumVerticesPadded() const
Get the number of vertices in the vertex buffers padded to a multiple of mMaxVerticesPerStrand.
Definition HairSettings.h:254
uint32 mNumIterationsPerSecond
Definition HairSettings.h:344
Holds a 4x4 matrix of floats, but supports also operations on the 3x3 upper left part of the matrix.
Definition Mat44.h:13
Definition Reference.h:110
Simple binary input stream.
Definition StreamIn.h:13
Simple binary output stream.
Definition StreamOut.h:13
Definition UVec4.h:12
static JPH_INLINE UVec4 sMin(UVec4Arg inV1, UVec4Arg inV2)
Return the minimum value of each of the components.
Definition UVec4.inl:156
JPH_INLINE Vec4 ToFloat() const
Convert each component from an int to a float.
Definition UVec4.inl:510
Definition Vec3.h:17
static JPH_INLINE Vec3 sMax(Vec3Arg inV1, Vec3Arg inV2)
Return the maximum of each of the components.
Definition Vec3.inl:203
static JPH_INLINE Vec3 sMin(Vec3Arg inV1, Vec3Arg inV2)
Return the minimum value of each of the components.
Definition Vec3.inl:183
JPH_INLINE float GetX() const
Get individual components.
Definition Vec3.h:127
JPH_INLINE float GetY() const
Definition Vec3.h:128
static JPH_INLINE Vec3 sZero()
Vector with all zeros.
Definition Vec3.inl:125
static JPH_INLINE Vec3 sReplicate(float inV)
Replicate inV across all components.
Definition Vec3.inl:141
JPH_INLINE float GetZ() const
Definition Vec3.h:129
Definition Vec4.h:14
The material determines the simulation parameters for a hair strand.
Definition HairSettings.h:188
Gradient mGridVelocityFactor
Every iteration this fraction of the grid velocity will be applied to the vertex velocity....
Definition HairSettings.h:222
float mMaxAngularVelocity
Maximum angular velocity of a vertex.
Definition HairSettings.h:213
float mGridDensityForceFactor
This factor will try to push the density of the hair towards the neutral density defined in the densi...
Definition HairSettings.h:223
Gradient mGravityFactor
How much gravity affects the hair along its length, 0 = no gravity, 1 = full gravity....
Definition HairSettings.h:214
float mInertiaMultiplier
Multiplier applied to the mass of a rod to calculate its inertia.
Definition HairSettings.h:219
Gradient mSkinGlobalPose
How much the global pose follows the skin of the scalp. 0 is not following, 1 is fully following.
Definition HairSettings.h:225
bool mEnableLRA
Enable Long Range Attachments to keep hair close to the modeled pose. This prevents excessive stretch...
Definition HairSettings.h:209
bool GlobalPoseOnly() const
If this material only needs running the global pose logic.
Definition HairSettings.h:195
bool NeedsGrid() const
Returns if this material needs a density/velocity grid.
Definition HairSettings.h:192
float mAngularDamping
Angular damping coefficient for the simulated rods.
Definition HairSettings.h:211
float mMaxLinearVelocity
Maximum linear velocity of a vertex.
Definition HairSettings.h:212
float GetBendCompliance(float inStrandFraction) const
Calculate the bend compliance at a fraction along the strand.
Definition HairSettings.h:198
Gradient mWorldTransformInfluence
How much rotating the head influences the hair, 0 = not at all, the hair will move with the head as i...
Definition HairSettings.h:221
float mGravityPreloadFactor
Note: Not fully functional yet! This controls how much of the gravity we will remove from the modeled...
Definition HairSettings.h:227
Gradient mGlobalPose
Every iteration this fraction of the neutral pose will be applied to the vertex position....
Definition HairSettings.h:224
bool mEnableCollision
Enable collision detection between hair strands and the environment.
Definition HairSettings.h:208
float mStretchCompliance
Compliance for stretch constraints: 1 / stiffness.
Definition HairSettings.h:218
Gradient mHairRadius
Radius of the hair strand along its length, used for collision detection.
Definition HairSettings.h:220
float mFriction
Collision friction coefficient. Usually in the range [0, 1]. 0 = no friction.
Definition HairSettings.h:215
float mBendCompliance
Compliance for bend constraints: 1 / stiffness.
Definition HairSettings.h:216
float mLinearDamping
Linear damping coefficient for the simulated rods.
Definition HairSettings.h:210
float mSimulationStrandsFraction
Used by InitRenderAndSimulationStrands only. Indicates the fraction of strands that should be simulat...
Definition HairSettings.h:226
Float4 mBendComplianceMultiplier
Multiplier for bend compliance at 0%, 33%, 66% and 100% of the strand length.
Definition HairSettings.h:217
float MeasureLength(const Array< SVertex > &inVertices) const
Definition HairSettings.h:85
uint32 mStartVtx
Definition HairSettings.h:93
uint32 mEndVtx
Definition HairSettings.h:94
RStrand()=default
Constructor.
uint32 VertexCount() const
Definition HairSettings.h:83
A render vertex.
Definition HairSettings.h:50
Float3 mPosition
Initial position of the vertex.
Definition HairSettings.h:53
SVertexInfluence mInfluences[cHairNumSVertexInfluences]
Attach to X simulated vertices (computed during Init).
Definition HairSettings.h:54
A hair simulation strand.
Definition HairSettings.h:99
uint32 mMaterialIndex
Index in mMaterials.
Definition HairSettings.h:105
float mLength
Initial distance of this vertex to the next of the unloaded strand, computed by Init.
Definition HairSettings.h:68
Float3 mPosition
Initial position of the vertex in its modeled pose.
Definition HairSettings.h:66
float mInvMass
Inverse of the mass of the vertex.
Definition HairSettings.h:67
float mStrandFraction
Fraction along the strand, 0 = start, 1 = end, computed by Init.
Definition HairSettings.h:69
Float4 mBishop
Bishop frame of the strand in its modeled pose, computed by Init.
Definition HairSettings.h:70
SVertex()=default
Constructor.
Float4 mOmega0
Conjugate(Previous Bishop) * Bishop, defines the rotation difference between the previous rod and thi...
Definition HairSettings.h:71
Describes how a render vertex is influenced by a simulated vertex.
Definition HairSettings.h:42
SVertexInfluence()
Definition HairSettings.h:45
Information about where a hair strand is attached to the scalp mesh.
Definition HairSettings.h:34
How much a vertex is influenced by a joint.
Definition HairSettings.h:28