@@ -37,6 +37,7 @@ namespace
37
37
VoxelDouble2 point;
38
38
WorldDouble3 bboxMin, bboxMax; // Centered on the entity in model space
39
39
double animMaxHeight;
40
+ double feetY;
40
41
char initialAnimStateIndex;
41
42
bool isSensorCollider;
42
43
std::optional<Double2> direction;
@@ -50,14 +51,15 @@ namespace
50
51
{
51
52
this ->defID = -1 ;
52
53
this ->animMaxHeight = 0.0 ;
54
+ this ->feetY = 0.0 ;
53
55
this ->initialAnimStateIndex = -1 ;
54
56
this ->isSensorCollider = false ;
55
57
this ->hasInventory = false ;
56
58
this ->hasCreatureSound = false ;
57
59
}
58
60
};
59
61
60
- bool TryCreatePhysicsCollider (const CoordDouble2 &coord, double colliderHeight, double ceilingScale , bool isSensor, JPH::PhysicsSystem &physicsSystem, JPH::BodyID *outBodyID)
62
+ bool TryCreatePhysicsCollider (const CoordDouble2 &coord, double colliderHeight, double feetY , bool isSensor, JPH::PhysicsSystem &physicsSystem, JPH::BodyID *outBodyID)
61
63
{
62
64
JPH::BodyInterface &bodyInterface = physicsSystem.GetBodyInterface ();
63
65
@@ -82,7 +84,7 @@ namespace
82
84
const WorldDouble2 capsuleWorldPointXZ = VoxelUtils::coordToWorldPoint (coord); // @todo: use getEntityCorrectedY()
83
85
const JPH::RVec3 capsuleJoltPos (
84
86
static_cast <float >(capsuleWorldPointXZ.x ),
85
- static_cast <float >(ceilingScale + capsuleHalfTotalHeight),
87
+ static_cast <float >(feetY + capsuleHalfTotalHeight),
86
88
static_cast <float >(capsuleWorldPointXZ.y ));
87
89
const JPH::Quat capsuleJoltQuat = JPH::Quat::sRotation (JPH::Vec3Arg::sAxisY (), 0 .0f );
88
90
const JPH::ObjectLayer capsuleObjectLayer = isSensor ? PhysicsLayers::SENSOR : PhysicsLayers::MOVING;
@@ -133,6 +135,17 @@ namespace
133
135
134
136
return animTextureRefs;
135
137
}
138
+
139
+ double GetElevatedPlatformHeight (const VoxelShapeDefinition &voxelShapeDef)
140
+ {
141
+ if (!voxelShapeDef.isElevatedPlatform )
142
+ {
143
+ return 0.0 ;
144
+ }
145
+
146
+ DebugAssert (voxelShapeDef.type == VoxelShapeType::Box);
147
+ return voxelShapeDef.box .yOffset + voxelShapeDef.box .height ;
148
+ }
136
149
}
137
150
138
151
const EntityDefinition &EntityChunkManager::getEntityDef (EntityDefID defID) const
@@ -231,7 +244,7 @@ void EntityChunkManager::populateChunkEntities(EntityChunk &entityChunk, const V
231
244
232
245
animInst.setStateIndex (initInfo.initialAnimStateIndex );
233
246
234
- if (!TryCreatePhysicsCollider (entityCoord, initInfo.animMaxHeight , ceilingScale , initInfo.isSensorCollider , physicsSystem, &entityInst.physicsBodyID ))
247
+ if (!TryCreatePhysicsCollider (entityCoord, initInfo.animMaxHeight , initInfo. feetY , initInfo.isSensorCollider , physicsSystem, &entityInst.physicsBodyID ))
235
248
{
236
249
DebugLogError (" Couldn't allocate entity Jolt physics body." );
237
250
}
@@ -316,10 +329,11 @@ void EntityChunkManager::populateChunkEntities(EntityChunk &entityChunk, const V
316
329
DebugAssert (initialAnimStateIndex.has_value ());
317
330
318
331
std::optional<EntityDefID> entityDefID; // Global entity def ID (shared across all active chunks).
319
- for (const WorldDouble3 &position : placementDef.positions )
332
+ for (const WorldDouble2 &worldPosition : placementDef.positions )
320
333
{
321
- const WorldInt3 voxelPosition = VoxelUtils::pointToVoxel (position, ceilingScale);
322
- if (!ChunkUtils::IsInWritingRange (voxelPosition, startX, endX, startY, endY, startZ, endZ))
334
+ const WorldInt2 worldVoxelXZ = VoxelUtils::pointToVoxel (worldPosition);
335
+ const WorldInt3 worldVoxel (worldVoxelXZ.x , 1 , worldVoxelXZ.y );
336
+ if (!ChunkUtils::IsInWritingRange (worldVoxel, startX, endX, startY, endY, startZ, endZ))
323
337
{
324
338
continue ;
325
339
}
@@ -329,21 +343,27 @@ void EntityChunkManager::populateChunkEntities(EntityChunk &entityChunk, const V
329
343
entityDefID = this ->getOrAddEntityDefID (entityDef, entityDefLibrary);
330
344
}
331
345
332
- const VoxelDouble3 point = ChunkUtils::MakeChunkPointFromLevel (position, startX, startY, startZ);
346
+ const VoxelDouble2 point = ChunkUtils::MakeChunkPointFromLevel (worldPosition, startX, startZ);
347
+ const VoxelInt3 voxel = VoxelUtils::worldVoxelToCoord (worldVoxel).voxel ;
333
348
334
349
double animMaxWidth, animMaxHeight;
335
350
EntityUtils::getAnimationMaxDims (animDef, &animMaxWidth, &animMaxHeight);
336
351
const double halfAnimMaxWidth = animMaxWidth * 0.50 ;
337
352
338
353
EntityInitInfo initInfo;
339
354
initInfo.defID = *entityDefID;
340
- initInfo.point = VoxelDouble2 ( point. x , point. z ) ;
355
+ initInfo.point = point;
341
356
342
357
// Bounding box is centered on the entity in model space.
343
358
initInfo.bboxMin = WorldDouble3 (-halfAnimMaxWidth, 0.0 , -halfAnimMaxWidth);
344
359
initInfo.bboxMax = WorldDouble3 (halfAnimMaxWidth, animMaxHeight, halfAnimMaxWidth);
345
360
346
361
initInfo.animMaxHeight = animMaxHeight;
362
+
363
+ const VoxelShapeDefID voxelShapeDefID = voxelChunk.getShapeDefID (voxel.x , voxel.y , voxel.z );
364
+ const VoxelShapeDefinition &voxelShapeDef = voxelChunk.getShapeDef (voxelShapeDefID);
365
+ initInfo.feetY = ceilingScale + GetElevatedPlatformHeight (voxelShapeDef);
366
+
347
367
initInfo.initialAnimStateIndex = *initialAnimStateIndex;
348
368
initInfo.isSensorCollider = !EntityUtils::hasCollision (entityDef);
349
369
@@ -424,6 +444,7 @@ void EntityChunkManager::populateChunkEntities(EntityChunk &entityChunk, const V
424
444
citizenInitInfo.bboxMax = WorldDouble3 (halfAnimMaxWidth, animMaxHeight, halfAnimMaxWidth);
425
445
426
446
citizenInitInfo.animMaxHeight = animMaxHeight;
447
+ citizenInitInfo.feetY = ceilingScale;
427
448
citizenInitInfo.initialAnimStateIndex = *initialCitizenAnimStateIndex;
428
449
citizenInitInfo.isSensorCollider = true ;
429
450
citizenInitInfo.citizenDirectionIndex = CitizenUtils::getRandomCitizenDirectionIndex (random );
0 commit comments