Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/HeightFieldShape.h
9913 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#pragma once
6
7
#include <Jolt/Physics/Collision/Shape/Shape.h>
8
#include <Jolt/Physics/Collision/PhysicsMaterial.h>
9
#ifdef JPH_DEBUG_RENDERER
10
#include <Jolt/Renderer/DebugRenderer.h>
11
#endif // JPH_DEBUG_RENDERER
12
13
JPH_NAMESPACE_BEGIN
14
15
class ConvexShape;
16
class CollideShapeSettings;
17
class TempAllocator;
18
19
/// Constants for HeightFieldShape, this was moved out of the HeightFieldShape because of a linker bug
20
namespace HeightFieldShapeConstants
21
{
22
/// Value used to create gaps in the height field
23
constexpr float cNoCollisionValue = FLT_MAX;
24
25
/// Stack size to use during WalkHeightField
26
constexpr int cStackSize = 128;
27
28
/// A position in the hierarchical grid is defined by a level (which grid), x and y position. We encode this in a single uint32 as: level << 28 | y << 14 | x
29
constexpr uint cNumBitsXY = 14;
30
constexpr uint cMaskBitsXY = (1 << cNumBitsXY) - 1;
31
constexpr uint cLevelShift = 2 * cNumBitsXY;
32
33
/// When height samples are converted to 16 bit:
34
constexpr uint16 cNoCollisionValue16 = 0xffff; ///< This is the magic value for 'no collision'
35
constexpr uint16 cMaxHeightValue16 = 0xfffe; ///< This is the maximum allowed height value
36
};
37
38
/// Class that constructs a HeightFieldShape
39
class JPH_EXPORT HeightFieldShapeSettings final : public ShapeSettings
40
{
41
JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, HeightFieldShapeSettings)
42
43
public:
44
/// Default constructor for deserialization
45
HeightFieldShapeSettings() = default;
46
47
/// Create a height field shape of inSampleCount * inSampleCount vertices.
48
/// The height field is a surface defined by: inOffset + inScale * (x, inSamples[y * inSampleCount + x], y).
49
/// where x and y are integers in the range x and y e [0, inSampleCount - 1].
50
/// inSampleCount: inSampleCount / mBlockSize must be minimally 2 and a power of 2 is the most efficient in terms of performance and storage.
51
/// inSamples: inSampleCount^2 vertices.
52
/// inMaterialIndices: (inSampleCount - 1)^2 indices that index into inMaterialList.
53
HeightFieldShapeSettings(const float *inSamples, Vec3Arg inOffset, Vec3Arg inScale, uint32 inSampleCount, const uint8 *inMaterialIndices = nullptr, const PhysicsMaterialList &inMaterialList = PhysicsMaterialList());
54
55
// See: ShapeSettings
56
virtual ShapeResult Create() const override;
57
58
/// Determine the minimal and maximal value of mHeightSamples (will ignore cNoCollisionValue)
59
/// @param outMinValue The minimal value of mHeightSamples or FLT_MAX if no samples have collision
60
/// @param outMaxValue The maximal value of mHeightSamples or -FLT_MAX if no samples have collision
61
/// @param outQuantizationScale (value - outMinValue) * outQuantizationScale quantizes a height sample to 16 bits
62
void DetermineMinAndMaxSample(float &outMinValue, float &outMaxValue, float &outQuantizationScale) const;
63
64
/// Given mBlockSize, mSampleCount and mHeightSamples, calculate the amount of bits needed to stay below absolute error inMaxError
65
/// @param inMaxError Maximum allowed error in mHeightSamples after compression (note that this does not take mScale.Y into account)
66
/// @return Needed bits per sample in the range [1, 8].
67
uint32 CalculateBitsPerSampleForError(float inMaxError) const;
68
69
/// The height field is a surface defined by: mOffset + mScale * (x, mHeightSamples[y * mSampleCount + x], y).
70
/// where x and y are integers in the range x and y e [0, mSampleCount - 1].
71
Vec3 mOffset = Vec3::sZero();
72
Vec3 mScale = Vec3::sOne();
73
uint32 mSampleCount = 0;
74
75
/// Artificial minimal value of mHeightSamples, used for compression and can be used to update the terrain after creating with lower height values. If there are any lower values in mHeightSamples, this value will be ignored.
76
float mMinHeightValue = cLargeFloat;
77
78
/// Artificial maximum value of mHeightSamples, used for compression and can be used to update the terrain after creating with higher height values. If there are any higher values in mHeightSamples, this value will be ignored.
79
float mMaxHeightValue = -cLargeFloat;
80
81
/// When bigger than mMaterials.size() the internal material list will be preallocated to support this number of materials.
82
/// This avoids reallocations when calling HeightFieldShape::SetMaterials with new materials later.
83
uint32 mMaterialsCapacity = 0;
84
85
/// The heightfield is divided in blocks of mBlockSize * mBlockSize * 2 triangles and the acceleration structure culls blocks only,
86
/// bigger block sizes reduce memory consumption but also reduce query performance. Sensible values are [2, 8], does not need to be
87
/// a power of 2. Note that at run-time we'll perform one more grid subdivision, so the effective block size is half of what is provided here.
88
uint32 mBlockSize = 2;
89
90
/// How many bits per sample to use to compress the height field. Can be in the range [1, 8].
91
/// Note that each sample is compressed relative to the min/max value of its block of mBlockSize * mBlockSize pixels so the effective precision is higher.
92
/// Also note that increasing mBlockSize saves more memory than reducing the amount of bits per sample.
93
uint32 mBitsPerSample = 8;
94
95
/// An array of mSampleCount^2 height samples. Samples are stored in row major order, so the sample at (x, y) is at index y * mSampleCount + x.
96
Array<float> mHeightSamples;
97
98
/// An array of (mSampleCount - 1)^2 material indices.
99
Array<uint8> mMaterialIndices;
100
101
/// The materials of square at (x, y) is: mMaterials[mMaterialIndices[x + y * (mSampleCount - 1)]]
102
PhysicsMaterialList mMaterials;
103
104
/// Cosine of the threshold angle (if the angle between the two triangles is bigger than this, the edge is active, note that a concave edge is always inactive).
105
/// Setting this value too small can cause ghost collisions with edges, setting it too big can cause depenetration artifacts (objects not depenetrating quickly).
106
/// Valid ranges are between cos(0 degrees) and cos(90 degrees). The default value is cos(5 degrees).
107
float mActiveEdgeCosThresholdAngle = 0.996195f; // cos(5 degrees)
108
};
109
110
/// A height field shape. Cannot be used as a dynamic object.
111
///
112
/// Note: If you're using HeightFieldShape and are querying data while modifying the shape you'll have a race condition.
113
/// In this case it is best to create a new HeightFieldShape using the Clone function. You replace the shape on a body using BodyInterface::SetShape.
114
/// If a query is still working on the old shape, it will have taken a reference and keep the old shape alive until the query finishes.
115
class JPH_EXPORT HeightFieldShape final : public Shape
116
{
117
public:
118
JPH_OVERRIDE_NEW_DELETE
119
120
/// Constructor
121
HeightFieldShape() : Shape(EShapeType::HeightField, EShapeSubType::HeightField) { }
122
HeightFieldShape(const HeightFieldShapeSettings &inSettings, ShapeResult &outResult);
123
virtual ~HeightFieldShape() override;
124
125
/// Clone this shape. Can be used to avoid race conditions. See the documentation of this class for more information.
126
Ref<HeightFieldShape> Clone() const;
127
128
// See Shape::MustBeStatic
129
virtual bool MustBeStatic() const override { return true; }
130
131
/// Get the size of the height field. Note that this will always be rounded up to the nearest multiple of GetBlockSize().
132
inline uint GetSampleCount() const { return mSampleCount; }
133
134
/// Get the size of a block
135
inline uint GetBlockSize() const { return mBlockSize; }
136
137
// See Shape::GetLocalBounds
138
virtual AABox GetLocalBounds() const override;
139
140
// See Shape::GetSubShapeIDBitsRecursive
141
virtual uint GetSubShapeIDBitsRecursive() const override { return GetSubShapeIDBits(); }
142
143
// See Shape::GetInnerRadius
144
virtual float GetInnerRadius() const override { return 0.0f; }
145
146
// See Shape::GetMassProperties
147
virtual MassProperties GetMassProperties() const override;
148
149
// See Shape::GetMaterial
150
virtual const PhysicsMaterial * GetMaterial(const SubShapeID &inSubShapeID) const override;
151
152
/// Overload to get the material at a particular location
153
const PhysicsMaterial * GetMaterial(uint inX, uint inY) const;
154
155
// See Shape::GetSurfaceNormal
156
virtual Vec3 GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;
157
158
// See Shape::GetSupportingFace
159
virtual void GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;
160
161
// See Shape::GetSubmergedVolume
162
virtual void GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy JPH_IF_DEBUG_RENDERER(, RVec3Arg inBaseOffset)) const override { JPH_ASSERT(false, "Not supported"); }
163
164
#ifdef JPH_DEBUG_RENDERER
165
// See Shape::Draw
166
virtual void Draw(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;
167
#endif // JPH_DEBUG_RENDERER
168
169
// See Shape::CastRay
170
virtual bool CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const override;
171
virtual void CastRay(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector, const ShapeFilter &inShapeFilter = { }) const override;
172
173
// See: Shape::CollidePoint
174
virtual void CollidePoint(Vec3Arg inPoint, const SubShapeIDCreator &inSubShapeIDCreator, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter = { }) const override;
175
176
// See: Shape::CollideSoftBodyVertices
177
virtual void CollideSoftBodyVertices(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const CollideSoftBodyVertexIterator &inVertices, uint inNumVertices, int inCollidingShapeIndex) const override;
178
179
// See Shape::GetTrianglesStart
180
virtual void GetTrianglesStart(GetTrianglesContext &ioContext, const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale) const override;
181
182
// See Shape::GetTrianglesNext
183
virtual int GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials = nullptr) const override;
184
185
/// Get height field position at sampled location (inX, inY).
186
/// where inX and inY are integers in the range inX e [0, mSampleCount - 1] and inY e [0, mSampleCount - 1].
187
Vec3 GetPosition(uint inX, uint inY) const;
188
189
/// Check if height field at sampled location (inX, inY) has collision (has a hole or not)
190
bool IsNoCollision(uint inX, uint inY) const;
191
192
/// Projects inLocalPosition (a point in the space of the shape) along the Y axis onto the surface and returns it in outSurfacePosition.
193
/// When there is no surface position (because of a hole or because the point is outside the heightfield) the function will return false.
194
bool ProjectOntoSurface(Vec3Arg inLocalPosition, Vec3 &outSurfacePosition, SubShapeID &outSubShapeID) const;
195
196
/// Returns the coordinates of the triangle that a sub shape ID represents
197
/// @param inSubShapeID The sub shape ID to decode
198
/// @param outX X coordinate of the triangle (in the range [0, mSampleCount - 2])
199
/// @param outY Y coordinate of the triangle (in the range [0, mSampleCount - 2])
200
/// @param outTriangleIndex Triangle within the quad (0 = lower triangle or 1 = upper triangle)
201
void GetSubShapeCoordinates(const SubShapeID &inSubShapeID, uint &outX, uint &outY, uint &outTriangleIndex) const;
202
203
/// Get the range of height values that this height field can encode. Can be used to determine the allowed range when setting the height values with SetHeights.
204
float GetMinHeightValue() const { return mOffset.GetY(); }
205
float GetMaxHeightValue() const { return mOffset.GetY() + mScale.GetY() * HeightFieldShapeConstants::cMaxHeightValue16; }
206
207
/// Get the height values of a block of data.
208
/// Note that the height values are decompressed so will be slightly different from what the shape was originally created with.
209
/// @param inX Start X position, must be a multiple of mBlockSize and in the range [0, mSampleCount - 1]
210
/// @param inY Start Y position, must be a multiple of mBlockSize and in the range [0, mSampleCount - 1]
211
/// @param inSizeX Number of samples in X direction, must be a multiple of mBlockSize and in the range [0, mSampleCount - inX]
212
/// @param inSizeY Number of samples in Y direction, must be a multiple of mBlockSize and in the range [0, mSampleCount - inY]
213
/// @param outHeights Returned height values, must be at least inSizeX * inSizeY floats. Values are returned in x-major order and can be cNoCollisionValue.
214
/// @param inHeightsStride Stride in floats between two consecutive rows of outHeights (can be negative if the data is upside down).
215
void GetHeights(uint inX, uint inY, uint inSizeX, uint inSizeY, float *outHeights, intptr_t inHeightsStride) const;
216
217
/// Set the height values of a block of data.
218
/// Note that this requires decompressing and recompressing a border of size mBlockSize in the negative x/y direction so will cause some precision loss.
219
/// Beware this can create a race condition if you're running collision queries in parallel. See class documentation for more information.
220
/// @param inX Start X position, must be a multiple of mBlockSize and in the range [0, mSampleCount - 1]
221
/// @param inY Start Y position, must be a multiple of mBlockSize and in the range [0, mSampleCount - 1]
222
/// @param inSizeX Number of samples in X direction, must be a multiple of mBlockSize and in the range [0, mSampleCount - inX]
223
/// @param inSizeY Number of samples in Y direction, must be a multiple of mBlockSize and in the range [0, mSampleCount - inY]
224
/// @param inHeights The new height values to set, must be an array of inSizeX * inSizeY floats, can be cNoCollisionValue. Values outside of the range [GetMinHeightValue(), GetMaxHeightValue()] will be clamped.
225
/// @param inHeightsStride Stride in floats between two consecutive rows of inHeights (can be negative if the data is upside down).
226
/// @param inAllocator Allocator to use for temporary memory
227
/// @param inActiveEdgeCosThresholdAngle Cosine of the threshold angle (if the angle between the two triangles is bigger than this, the edge is active, note that a concave edge is always inactive).
228
void SetHeights(uint inX, uint inY, uint inSizeX, uint inSizeY, const float *inHeights, intptr_t inHeightsStride, TempAllocator &inAllocator, float inActiveEdgeCosThresholdAngle = 0.996195f);
229
230
/// Get the current list of materials, the indices returned by GetMaterials() will index into this list.
231
const PhysicsMaterialList & GetMaterialList() const { return mMaterials; }
232
233
/// Get the material indices of a block of data.
234
/// @param inX Start X position, must in the range [0, mSampleCount - 1]
235
/// @param inY Start Y position, must in the range [0, mSampleCount - 1]
236
/// @param inSizeX Number of samples in X direction
237
/// @param inSizeY Number of samples in Y direction
238
/// @param outMaterials Returned material indices, must be at least inSizeX * inSizeY uint8s. Values are returned in x-major order.
239
/// @param inMaterialsStride Stride in uint8s between two consecutive rows of outMaterials (can be negative if the data is upside down).
240
void GetMaterials(uint inX, uint inY, uint inSizeX, uint inSizeY, uint8 *outMaterials, intptr_t inMaterialsStride) const;
241
242
/// Set the material indices of a block of data.
243
/// Beware this can create a race condition if you're running collision queries in parallel. See class documentation for more information.
244
/// @param inX Start X position, must in the range [0, mSampleCount - 1]
245
/// @param inY Start Y position, must in the range [0, mSampleCount - 1]
246
/// @param inSizeX Number of samples in X direction
247
/// @param inSizeY Number of samples in Y direction
248
/// @param inMaterials The new material indices, must be at least inSizeX * inSizeY uint8s. Values are returned in x-major order.
249
/// @param inMaterialsStride Stride in uint8s between two consecutive rows of inMaterials (can be negative if the data is upside down).
250
/// @param inMaterialList The material list to use for the new material indices or nullptr if the material list should not be updated
251
/// @param inAllocator Allocator to use for temporary memory
252
/// @return True if the material indices were set, false if the total number of materials exceeded 256
253
bool SetMaterials(uint inX, uint inY, uint inSizeX, uint inSizeY, const uint8 *inMaterials, intptr_t inMaterialsStride, const PhysicsMaterialList *inMaterialList, TempAllocator &inAllocator);
254
255
// See Shape
256
virtual void SaveBinaryState(StreamOut &inStream) const override;
257
virtual void SaveMaterialState(PhysicsMaterialList &outMaterials) const override;
258
virtual void RestoreMaterialState(const PhysicsMaterialRefC *inMaterials, uint inNumMaterials) override;
259
260
// See Shape::GetStats
261
virtual Stats GetStats() const override;
262
263
// See Shape::GetVolume
264
virtual float GetVolume() const override { return 0; }
265
266
#ifdef JPH_DEBUG_RENDERER
267
// Settings
268
static bool sDrawTriangleOutlines;
269
#endif // JPH_DEBUG_RENDERER
270
271
// Register shape functions with the registry
272
static void sRegister();
273
274
protected:
275
// See: Shape::RestoreBinaryState
276
virtual void RestoreBinaryState(StreamIn &inStream) override;
277
278
private:
279
class DecodingContext; ///< Context class for walking through all nodes of a heightfield
280
struct HSGetTrianglesContext; ///< Context class for GetTrianglesStart/Next
281
282
/// Calculate commonly used values and store them in the shape
283
void CacheValues();
284
285
/// Allocate the mRangeBlocks, mHeightSamples and mActiveEdges buffers as a single data block
286
void AllocateBuffers();
287
288
/// Calculate bit mask for all active edges in the heightfield for a specific region
289
void CalculateActiveEdges(uint inX, uint inY, uint inSizeX, uint inSizeY, const float *inHeights, uint inHeightsStartX, uint inHeightsStartY, intptr_t inHeightsStride, float inHeightsScale, float inActiveEdgeCosThresholdAngle, TempAllocator &inAllocator);
290
291
/// Calculate bit mask for all active edges in the heightfield
292
void CalculateActiveEdges(const HeightFieldShapeSettings &inSettings);
293
294
/// Store material indices in the least amount of bits per index possible
295
void StoreMaterialIndices(const HeightFieldShapeSettings &inSettings);
296
297
/// Get the amount of horizontal/vertical blocks
298
inline uint GetNumBlocks() const { return mSampleCount / mBlockSize; }
299
300
/// Get the maximum level (amount of grids) of the tree
301
static inline uint sGetMaxLevel(uint inNumBlocks) { return 32 - CountLeadingZeros(inNumBlocks - 1); }
302
303
/// Get the range block offset and stride for GetBlockOffsetAndScale
304
static inline void sGetRangeBlockOffsetAndStride(uint inNumBlocks, uint inMaxLevel, uint &outRangeBlockOffset, uint &outRangeBlockStride);
305
306
/// For block (inBlockX, inBlockY) get the offset and scale needed to decode a uint8 height sample to a uint16
307
inline void GetBlockOffsetAndScale(uint inBlockX, uint inBlockY, uint inRangeBlockOffset, uint inRangeBlockStride, float &outBlockOffset, float &outBlockScale) const;
308
309
/// Get the height sample at position (inX, inY)
310
inline uint8 GetHeightSample(uint inX, uint inY) const;
311
312
/// Faster version of GetPosition when block offset and scale are already known
313
inline Vec3 GetPosition(uint inX, uint inY, float inBlockOffset, float inBlockScale, bool &outNoCollision) const;
314
315
/// Determine amount of bits needed to encode sub shape id
316
uint GetSubShapeIDBits() const;
317
318
/// En/decode a sub shape ID. inX and inY specify the coordinate of the triangle. inTriangle == 0 is the lower triangle, inTriangle == 1 is the upper triangle.
319
inline SubShapeID EncodeSubShapeID(const SubShapeIDCreator &inCreator, uint inX, uint inY, uint inTriangle) const;
320
inline void DecodeSubShapeID(const SubShapeID &inSubShapeID, uint &outX, uint &outY, uint &outTriangle) const;
321
322
/// Get the edge flags for a triangle
323
inline uint8 GetEdgeFlags(uint inX, uint inY, uint inTriangle) const;
324
325
// Helper functions called by CollisionDispatch
326
static void sCollideConvexVsHeightField(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector, const ShapeFilter &inShapeFilter);
327
static void sCollideSphereVsHeightField(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector, const ShapeFilter &inShapeFilter);
328
static void sCastConvexVsHeightField(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
329
static void sCastSphereVsHeightField(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);
330
331
/// Visit the entire height field using a visitor pattern
332
/// Note: Used to be inlined but this triggers a bug in MSVC where it will not free the memory allocated by alloca which causes a stack overflow when WalkHeightField is called in a loop (clang does it correct)
333
template <class Visitor>
334
void WalkHeightField(Visitor &ioVisitor) const;
335
336
/// A block of 2x2 ranges used to form a hierarchical grid, ordered left top, right top, left bottom, right bottom
337
struct alignas(16) RangeBlock
338
{
339
uint16 mMin[4];
340
uint16 mMax[4];
341
};
342
343
/// For block (inBlockX, inBlockY) get the range block and the entry in the range block
344
inline void GetRangeBlock(uint inBlockX, uint inBlockY, uint inRangeBlockOffset, uint inRangeBlockStride, RangeBlock *&outBlock, uint &outIndexInBlock);
345
346
/// Offset of first RangedBlock in grid per level
347
static const uint sGridOffsets[];
348
349
/// The height field is a surface defined by: mOffset + mScale * (x, mHeightSamples[y * mSampleCount + x], y).
350
/// where x and y are integers in the range x and y e [0, mSampleCount - 1].
351
Vec3 mOffset = Vec3::sZero();
352
Vec3 mScale = Vec3::sOne();
353
354
/// Height data
355
uint32 mSampleCount = 0; ///< See HeightFieldShapeSettings::mSampleCount
356
uint32 mBlockSize = 2; ///< See HeightFieldShapeSettings::mBlockSize
357
uint32 mHeightSamplesSize = 0; ///< Size of mHeightSamples in bytes
358
uint32 mRangeBlocksSize = 0; ///< Size of mRangeBlocks in elements
359
uint32 mActiveEdgesSize = 0; ///< Size of mActiveEdges in bytes
360
uint8 mBitsPerSample = 8; ///< See HeightFieldShapeSettings::mBitsPerSample
361
uint8 mSampleMask = 0xff; ///< All bits set for a sample: (1 << mBitsPerSample) - 1, used to indicate that there's no collision
362
uint16 mMinSample = HeightFieldShapeConstants::cNoCollisionValue16; ///< Min and max value in mHeightSamples quantized to 16 bit, for calculating bounding box
363
uint16 mMaxSample = HeightFieldShapeConstants::cNoCollisionValue16;
364
RangeBlock * mRangeBlocks = nullptr; ///< Hierarchical grid of range data describing the height variations within 1 block. The grid for level <level> starts at offset sGridOffsets[<level>]
365
uint8 * mHeightSamples = nullptr; ///< mBitsPerSample-bit height samples. Value [0, mMaxHeightValue] maps to highest detail grid in mRangeBlocks [mMin, mMax]. mNoCollisionValue is reserved to indicate no collision.
366
uint8 * mActiveEdges = nullptr; ///< (mSampleCount - 1)^2 * 3-bit active edge flags.
367
368
/// Materials
369
PhysicsMaterialList mMaterials; ///< The materials of square at (x, y) is: mMaterials[mMaterialIndices[x + y * (mSampleCount - 1)]]
370
Array<uint8> mMaterialIndices; ///< Compressed to the minimum amount of bits per material index (mSampleCount - 1) * (mSampleCount - 1) * mNumBitsPerMaterialIndex bits of data
371
uint32 mNumBitsPerMaterialIndex = 0; ///< Number of bits per material index
372
373
#ifdef JPH_DEBUG_RENDERER
374
/// Temporary rendering data
375
mutable Array<DebugRenderer::GeometryRef> mGeometry;
376
mutable bool mCachedUseMaterialColors = false; ///< This is used to regenerate the triangle batch if the drawing settings change
377
#endif // JPH_DEBUG_RENDERER
378
};
379
380
JPH_NAMESPACE_END
381
382