Skip to content

Commit 3b6480c

Browse files
committedFeb 23, 2015
Fix wrapDegrees family of functions
wrapDegrees() (renamed to modulo360f) wrapDegrees_0_360 wrapDegrees_180 Minor errors were present in previous versions; see issue #2328
1 parent 51057a5 commit 3b6480c

File tree

3 files changed

+80
-51
lines changed

3 files changed

+80
-51
lines changed
 

Diff for: ‎src/network/packethandlers/server.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -543,8 +543,8 @@ void Server::handleCommand_PlayerPos(NetworkPacket* pkt)
543543
v3f position((f32)ps.X / 100.0, (f32)ps.Y / 100.0, (f32)ps.Z / 100.0);
544544
v3f speed((f32)ss.X / 100.0, (f32)ss.Y / 100.0, (f32)ss.Z / 100.0);
545545

546-
pitch = wrapDegrees(pitch);
547-
yaw = wrapDegrees(yaw);
546+
pitch = modulo360f(pitch);
547+
yaw = modulo360f(yaw);
548548

549549
Player *player = m_env->getPlayer(pkt->getPeerId());
550550
if (player == NULL) {

Diff for: ‎src/test.cpp

+37-7
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,45 @@ struct TestBase
147147

148148
struct TestUtilities: public TestBase
149149
{
150+
inline float ref_WrapDegrees180(float f)
151+
{
152+
// This is a slower alternative to the wrapDegrees_180() function;
153+
// used as a reference for testing
154+
float value = fmodf(f + 180, 360);
155+
if (value < 0)
156+
value += 360;
157+
return value - 180;
158+
}
159+
160+
inline float ref_WrapDegrees_0_360(float f)
161+
{
162+
// This is a slower alternative to the wrapDegrees_0_360() function;
163+
// used as a reference for testing
164+
float value = fmodf(f, 360);
165+
if (value < 0)
166+
value += 360;
167+
return value < 0 ? value + 360 : value;
168+
}
169+
170+
150171
void Run()
151172
{
152-
/*infostream<<"wrapDegrees(100.0) = "<<wrapDegrees(100.0)<<std::endl;
153-
infostream<<"wrapDegrees(720.5) = "<<wrapDegrees(720.5)<<std::endl;
154-
infostream<<"wrapDegrees(-0.5) = "<<wrapDegrees(-0.5)<<std::endl;*/
155-
UASSERT(fabs(wrapDegrees(100.0) - 100.0) < 0.001);
156-
UASSERT(fabs(wrapDegrees(720.5) - 0.5) < 0.001);
157-
UASSERT(fabs(wrapDegrees(-0.5) - (-0.5)) < 0.001);
158-
UASSERT(fabs(wrapDegrees(-365.5) - (-5.5)) < 0.001);
173+
UASSERT(fabs(modulo360f(100.0) - 100.0) < 0.001);
174+
UASSERT(fabs(modulo360f(720.5) - 0.5) < 0.001);
175+
UASSERT(fabs(modulo360f(-0.5) - (-0.5)) < 0.001);
176+
UASSERT(fabs(modulo360f(-365.5) - (-5.5)) < 0.001);
177+
178+
for (float f = -720; f <= -360; f += 0.25) {
179+
UASSERT(fabs(modulo360f(f) - modulo360f(f + 360)) < 0.001);
180+
}
181+
182+
for (float f = -1440; f <= 1440; f += 0.25) {
183+
UASSERT(fabs(modulo360f(f) - fmodf(f, 360)) < 0.001);
184+
UASSERT(fabs(wrapDegrees_180(f) - ref_WrapDegrees180(f)) < 0.001);
185+
UASSERT(fabs(wrapDegrees_0_360(f) - ref_WrapDegrees_0_360(f)) < 0.001);
186+
UASSERT(wrapDegrees_0_360(fabs(wrapDegrees_180(f) - wrapDegrees_0_360(f))) < 0.001);
187+
}
188+
159189
UASSERT(lowercase("Foo bAR") == "foo bar");
160190
UASSERT(trim("\n \t\r Foo bAR \r\n\t\t ") == "Foo bAR");
161191
UASSERT(trim("\n \t\r \r\n\t\t ") == "");

Diff for: ‎src/util/numeric.h

+41-42
Original file line numberDiff line numberDiff line change
@@ -184,57 +184,56 @@ inline void sortBoxVerticies(v3s16 &p1, v3s16 &p2) {
184184
}
185185

186186

187-
/*
188-
See test.cpp for example cases.
189-
wraps degrees to the range of -360...360
190-
NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
191-
*/
192-
inline float wrapDegrees(float f)
187+
/** Returns \p f wrapped to the range [-360, 360]
188+
*
189+
* See test.cpp for example cases.
190+
*
191+
* \note This is also used in cases where degrees wrapped to the range [0, 360]
192+
* is innapropriate (e.g. pitch needs negative values)
193+
*
194+
* \internal functionally equivalent -- although precision may vary slightly --
195+
* to fmodf((f), 360.0f) however empirical tests indicate that this approach is
196+
* faster.
197+
*/
198+
inline float modulo360f(float f)
193199
{
194-
// Take examples of f=10, f=720.5, f=-0.5, f=-360.5
195-
// This results in
196-
// 10, 720, -1, -361
197-
int i = floor(f);
198-
// 0, 2, 0, -1
199-
int l = i / 360;
200-
// NOTE: This would be used for wrapping to 0...360
201-
// 0, 2, -1, -2
202-
/*if(i < 0)
203-
l -= 1;*/
204-
// 0, 720, 0, -360
205-
int k = l * 360;
206-
// 10, 0.5, -0.5, -0.5
207-
f -= float(k);
208-
return f;
200+
int sign;
201+
int whole;
202+
float fraction;
203+
204+
if (f < 0) {
205+
f = -f;
206+
sign = -1;
207+
} else {
208+
sign = 1;
209+
}
210+
211+
whole = f;
212+
213+
fraction = f - whole;
214+
whole %= 360;
215+
216+
return sign * (whole + fraction);
209217
}
210218

211-
/* Wrap to 0...360 */
219+
220+
/** Returns \p f wrapped to the range [0, 360]
221+
*/
212222
inline float wrapDegrees_0_360(float f)
213223
{
214-
// Take examples of f=10, f=720.5, f=-0.5, f=-360.5
215-
// This results in
216-
// 10, 720, -1, -361
217-
int i = floor(f);
218-
// 0, 2, 0, -1
219-
int l = i / 360;
220-
// Wrap to 0...360
221-
// 0, 2, -1, -2
222-
if(i < 0)
223-
l -= 1;
224-
// 0, 720, 0, -360
225-
int k = l * 360;
226-
// 10, 0.5, -0.5, -0.5
227-
f -= float(k);
228-
return f;
224+
float value = modulo360f(f);
225+
return value < 0 ? value + 360 : value;
229226
}
230227

231-
/* Wrap to -180...180 */
228+
229+
/** Returns \p f wrapped to the range [-180, 180]
230+
*/
232231
inline float wrapDegrees_180(float f)
233232
{
234-
f += 180;
235-
f = wrapDegrees_0_360(f);
236-
f -= 180;
237-
return f;
233+
float value = modulo360f(f + 180);
234+
if (value < 0)
235+
value += 360;
236+
return value - 180;
238237
}
239238

240239
/*

0 commit comments

Comments
 (0)
Please sign in to comment.