@@ -66,6 +66,22 @@ struct NearbyCollisionInfo {
66
66
aabb3f box;
67
67
};
68
68
69
+ // Helper functions:
70
+ // Truncate floating point numbers to specified number of decimal places
71
+ // in order to move all the floating point error to one side of the correct value
72
+ static inline f32 truncate (const f32 val, const f32 factor)
73
+ {
74
+ return truncf (val * factor) / factor;
75
+ }
76
+
77
+ static inline v3f truncate (const v3f& vec, const f32 factor)
78
+ {
79
+ return v3f (
80
+ truncate (vec.X , factor),
81
+ truncate (vec.Y , factor),
82
+ truncate (vec.Z , factor)
83
+ );
84
+ }
69
85
70
86
// Helper function:
71
87
// Checks for collision of a moving aabbox with a static aabbox
@@ -78,95 +94,94 @@ CollisionAxis axisAlignedCollision(
78
94
// TimeTaker tt("axisAlignedCollision");
79
95
80
96
aabb3f relbox (
81
- movingbox.MaxEdge .X - movingbox.MinEdge .X + staticbox.MaxEdge .X - staticbox.MinEdge .X , // sum of the widths
82
- movingbox.MaxEdge .Y - movingbox.MinEdge .Y + staticbox.MaxEdge .Y - staticbox.MinEdge .Y ,
83
- movingbox.MaxEdge .Z - movingbox.MinEdge .Z + staticbox.MaxEdge .Z - staticbox.MinEdge .Z ,
97
+ ( movingbox.MaxEdge .X - movingbox.MinEdge .X ) + ( staticbox.MaxEdge .X - staticbox.MinEdge .X ) , // sum of the widths
98
+ ( movingbox.MaxEdge .Y - movingbox.MinEdge .Y ) + ( staticbox.MaxEdge .Y - staticbox.MinEdge .Y ) ,
99
+ ( movingbox.MaxEdge .Z - movingbox.MinEdge .Z ) + ( staticbox.MaxEdge .Z - staticbox.MinEdge .Z ) ,
84
100
std::max (movingbox.MaxEdge .X , staticbox.MaxEdge .X ) - std::min (movingbox.MinEdge .X , staticbox.MinEdge .X ), // outer bounding 'box' dimensions
85
101
std::max (movingbox.MaxEdge .Y , staticbox.MaxEdge .Y ) - std::min (movingbox.MinEdge .Y , staticbox.MinEdge .Y ),
86
102
std::max (movingbox.MaxEdge .Z , staticbox.MaxEdge .Z ) - std::min (movingbox.MinEdge .Z , staticbox.MinEdge .Z )
87
103
);
88
104
89
105
const f32 dtime_max = *dtime;
90
- const f32 inner_margin = - 1 . 5f ;
106
+ f32 inner_margin; // the distance of clipping recovery
91
107
f32 distance;
92
108
f32 time ;
93
109
94
- if (speed.X ) {
95
- distance = relbox.MaxEdge .X - relbox.MinEdge .X ;
96
110
97
- *dtime = distance >= 0 ? std::abs (distance / speed.X ) : -std::abs (distance / speed.X );
111
+ if (speed.Y ) {
112
+ distance = relbox.MaxEdge .Y - relbox.MinEdge .Y ;
113
+ *dtime = distance / std::abs (speed.Y );
98
114
time = std::max (*dtime, 0 .0f );
99
115
100
- if (distance > inner_margin) {
101
- if (*dtime <= dtime_max) {
102
- if ((speed.X > 0 && staticbox.MaxEdge .X > movingbox.MaxEdge .X ) ||
103
- (speed.X < 0 && staticbox.MinEdge .X < movingbox.MinEdge .X )) {
104
- if (
105
- (std::max (movingbox.MaxEdge .Y + speed.Y * time , staticbox.MaxEdge .Y )
106
- - std::min (movingbox.MinEdge .Y + speed.Y * time , staticbox.MinEdge .Y )
107
- - relbox.MinEdge .Y < 0 ) &&
116
+ if (*dtime <= dtime_max) {
117
+ inner_margin = std::max (-0 .5f * (staticbox.MaxEdge .Y - staticbox.MinEdge .Y ), -2 .0f );
118
+
119
+ if ((speed.Y > 0 && staticbox.MinEdge .Y - movingbox.MaxEdge .Y > inner_margin) ||
120
+ (speed.Y < 0 && movingbox.MinEdge .Y - staticbox.MaxEdge .Y > inner_margin)) {
121
+ if (
122
+ (std::max (movingbox.MaxEdge .X + speed.X * time , staticbox.MaxEdge .X )
123
+ - std::min (movingbox.MinEdge .X + speed.X * time , staticbox.MinEdge .X )
124
+ - relbox.MinEdge .X < 0 ) &&
108
125
(std::max (movingbox.MaxEdge .Z + speed.Z * time , staticbox.MaxEdge .Z )
109
126
- std::min (movingbox.MinEdge .Z + speed.Z * time , staticbox.MinEdge .Z )
110
127
- relbox.MinEdge .Z < 0 )
111
- )
112
- return COLLISION_AXIS_X;
113
- }
114
- } else {
115
- return COLLISION_AXIS_NONE;
128
+ )
129
+ return COLLISION_AXIS_Y;
116
130
}
117
131
}
132
+ else {
133
+ return COLLISION_AXIS_NONE;
134
+ }
118
135
}
119
136
120
137
// NO else if here
121
138
122
- if (speed.Y ) {
123
- distance = relbox.MaxEdge .Y - relbox.MinEdge .Y ;
124
-
125
- *dtime = distance >= 0 ? std::abs (distance / speed.Y ) : -std::abs (distance / speed.Y );
139
+ if (speed.X ) {
140
+ distance = relbox.MaxEdge .X - relbox.MinEdge .X ;
141
+ *dtime = distance / std::abs (speed.X );
126
142
time = std::max (*dtime, 0 .0f );
127
143
128
- if (distance > inner_margin) {
129
- if (*dtime <= dtime_max) {
130
- if ((speed.Y > 0 && staticbox.MaxEdge .Y > movingbox.MaxEdge .Y ) ||
131
- (speed.Y < 0 && staticbox.MinEdge .Y < movingbox.MinEdge .Y )) {
132
- if (
133
- (std::max (movingbox.MaxEdge .X + speed.X * time , staticbox.MaxEdge .X )
134
- - std::min (movingbox.MinEdge .X + speed.X * time , staticbox.MinEdge .X )
135
- - relbox.MinEdge .X < 0 ) &&
144
+ if (*dtime <= dtime_max) {
145
+ inner_margin = std::max (-0 .5f * (staticbox.MaxEdge .X - staticbox.MinEdge .X ), -2 .0f );
146
+
147
+ if ((speed.X > 0 && staticbox.MinEdge .X - movingbox.MaxEdge .X > inner_margin) ||
148
+ (speed.X < 0 && movingbox.MinEdge .X - staticbox.MaxEdge .X > inner_margin)) {
149
+ if (
150
+ (std::max (movingbox.MaxEdge .Y + speed.Y * time , staticbox.MaxEdge .Y )
151
+ - std::min (movingbox.MinEdge .Y + speed.Y * time , staticbox.MinEdge .Y )
152
+ - relbox.MinEdge .Y < 0 ) &&
136
153
(std::max (movingbox.MaxEdge .Z + speed.Z * time , staticbox.MaxEdge .Z )
137
154
- std::min (movingbox.MinEdge .Z + speed.Z * time , staticbox.MinEdge .Z )
138
155
- relbox.MinEdge .Z < 0 )
139
- )
140
- return COLLISION_AXIS_Y;
141
- }
142
- } else {
143
- return COLLISION_AXIS_NONE;
156
+ )
157
+ return COLLISION_AXIS_X;
144
158
}
159
+ } else {
160
+ return COLLISION_AXIS_NONE;
145
161
}
146
162
}
147
163
148
164
// NO else if here
149
165
150
166
if (speed.Z ) {
151
167
distance = relbox.MaxEdge .Z - relbox.MinEdge .Z ;
152
-
153
- *dtime = distance >= 0 ? std::abs (distance / speed.Z ) : -std::abs (distance / speed.Z );
168
+ *dtime = distance / std::abs (speed.Z );
154
169
time = std::max (*dtime, 0 .0f );
155
170
156
- if (distance > inner_margin) {
157
- if (*dtime <= dtime_max) {
158
- if ((speed.Z > 0 && staticbox.MaxEdge .Z > movingbox.MaxEdge .Z ) ||
159
- (speed.Z < 0 && staticbox.MinEdge .Z < movingbox.MinEdge .Z )) {
160
- if (
161
- (std::max (movingbox.MaxEdge .X + speed.X * time , staticbox.MaxEdge .X )
162
- - std::min (movingbox.MinEdge .X + speed.X * time , staticbox.MinEdge .X )
163
- - relbox.MinEdge .X < 0 ) &&
171
+ if (*dtime <= dtime_max) {
172
+ inner_margin = std::max (-0 .5f * (staticbox.MaxEdge .Z - staticbox.MinEdge .Z ), -2 .0f );
173
+
174
+ if ((speed.Z > 0 && staticbox.MinEdge .Z - movingbox.MaxEdge .Z > inner_margin) ||
175
+ (speed.Z < 0 && movingbox.MinEdge .Z - staticbox.MaxEdge .Z > inner_margin)) {
176
+ if (
177
+ (std::max (movingbox.MaxEdge .X + speed.X * time , staticbox.MaxEdge .X )
178
+ - std::min (movingbox.MinEdge .X + speed.X * time , staticbox.MinEdge .X )
179
+ - relbox.MinEdge .X < 0 ) &&
164
180
(std::max (movingbox.MaxEdge .Y + speed.Y * time , staticbox.MaxEdge .Y )
165
181
- std::min (movingbox.MinEdge .Y + speed.Y * time , staticbox.MinEdge .Y )
166
182
- relbox.MinEdge .Y < 0 )
167
- )
168
- return COLLISION_AXIS_Z;
169
- }
183
+ )
184
+ return COLLISION_AXIS_Z;
170
185
}
171
186
}
172
187
}
@@ -245,6 +260,8 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
245
260
speed_f->X = rangelim (speed_f->X , -5000 , 5000 );
246
261
speed_f->Z = rangelim (speed_f->Z , -5000 , 5000 );
247
262
263
+ *speed_f = truncate (*speed_f, 10000 .0f );
264
+
248
265
/*
249
266
Collect node boxes in movement range
250
267
*/
@@ -464,7 +481,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
464
481
465
482
if (nearest_collided == COLLISION_AXIS_NONE) {
466
483
// No collision with any collision box.
467
- *pos_f += *speed_f * dtime;
484
+ *pos_f += truncate ( *speed_f * dtime, 100 . 0f ) ;
468
485
dtime = 0 ; // Set to 0 to avoid "infinite" loop due to small FP numbers
469
486
} else {
470
487
// Otherwise, a collision occurred.
@@ -500,7 +517,7 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
500
517
pos_f->Z += speed_f->Z * nearest_dtime;
501
518
}
502
519
} else {
503
- *pos_f += *speed_f * nearest_dtime;
520
+ *pos_f += truncate ( *speed_f * nearest_dtime, 100 . 0f ) ;
504
521
dtime -= nearest_dtime;
505
522
}
506
523
0 commit comments