forked from Mirrorlandia_minetest/minetest
Network: Send IEEE floats (#7768)
This commit is contained in:
parent
8471d027b9
commit
839e935ba0
@ -1347,19 +1347,19 @@ void GenericCAO::processMessage(const std::string &data)
|
|||||||
} else if (cmd == GENERIC_CMD_UPDATE_POSITION) {
|
} else if (cmd == GENERIC_CMD_UPDATE_POSITION) {
|
||||||
// Not sent by the server if this object is an attachment.
|
// Not sent by the server if this object is an attachment.
|
||||||
// We might however get here if the server notices the object being detached before the client.
|
// We might however get here if the server notices the object being detached before the client.
|
||||||
m_position = readV3F1000(is);
|
m_position = readV3F32(is);
|
||||||
m_velocity = readV3F1000(is);
|
m_velocity = readV3F32(is);
|
||||||
m_acceleration = readV3F1000(is);
|
m_acceleration = readV3F32(is);
|
||||||
|
|
||||||
if (std::fabs(m_prop.automatic_rotate) < 0.001f)
|
if (std::fabs(m_prop.automatic_rotate) < 0.001f)
|
||||||
m_rotation = readV3F1000(is);
|
m_rotation = readV3F32(is);
|
||||||
else
|
else
|
||||||
readV3F1000(is);
|
readV3F32(is);
|
||||||
|
|
||||||
m_rotation = wrapDegrees_0_360_v3f(m_rotation);
|
m_rotation = wrapDegrees_0_360_v3f(m_rotation);
|
||||||
bool do_interpolate = readU8(is);
|
bool do_interpolate = readU8(is);
|
||||||
bool is_end_position = readU8(is);
|
bool is_end_position = readU8(is);
|
||||||
float update_interval = readF1000(is);
|
float update_interval = readF32(is);
|
||||||
|
|
||||||
// Place us a bit higher if we're physical, to not sink into
|
// Place us a bit higher if we're physical, to not sink into
|
||||||
// the ground due to sucky collision detection...
|
// the ground due to sucky collision detection...
|
||||||
|
@ -49,19 +49,19 @@ std::string gob_cmd_update_position(
|
|||||||
// command
|
// command
|
||||||
writeU8(os, GENERIC_CMD_UPDATE_POSITION);
|
writeU8(os, GENERIC_CMD_UPDATE_POSITION);
|
||||||
// pos
|
// pos
|
||||||
writeV3F1000(os, position);
|
writeV3F32(os, position);
|
||||||
// velocity
|
// velocity
|
||||||
writeV3F1000(os, velocity);
|
writeV3F32(os, velocity);
|
||||||
// acceleration
|
// acceleration
|
||||||
writeV3F1000(os, acceleration);
|
writeV3F32(os, acceleration);
|
||||||
// rotation
|
// rotation
|
||||||
writeV3F1000(os, rotation);
|
writeV3F32(os, rotation);
|
||||||
// do_interpolate
|
// do_interpolate
|
||||||
writeU8(os, do_interpolate);
|
writeU8(os, do_interpolate);
|
||||||
// is_end_position (for interpolation)
|
// is_end_position (for interpolation)
|
||||||
writeU8(os, is_movement_end);
|
writeU8(os, is_movement_end);
|
||||||
// update_interval (for interpolation)
|
// update_interval (for interpolation)
|
||||||
writeF1000(os, update_interval);
|
writeF32(os, update_interval);
|
||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,6 +191,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
PROTOCOL VERSION 37:
|
PROTOCOL VERSION 37:
|
||||||
Redo detached inventory sending
|
Redo detached inventory sending
|
||||||
Add TOCLIENT_NODEMETA_CHANGED
|
Add TOCLIENT_NODEMETA_CHANGED
|
||||||
|
New network float format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LATEST_PROTOCOL_VERSION 37
|
#define LATEST_PROTOCOL_VERSION 37
|
||||||
|
@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "util/serialize.h"
|
#include "util/serialize.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
class TestSerialization : public TestBase {
|
class TestSerialization : public TestBase {
|
||||||
public:
|
public:
|
||||||
@ -43,6 +44,7 @@ public:
|
|||||||
void testVecPut();
|
void testVecPut();
|
||||||
void testStringLengthLimits();
|
void testStringLengthLimits();
|
||||||
void testBufReader();
|
void testBufReader();
|
||||||
|
void testFloatFormat();
|
||||||
|
|
||||||
std::string teststring2;
|
std::string teststring2;
|
||||||
std::wstring teststring2_w;
|
std::wstring teststring2_w;
|
||||||
@ -70,6 +72,7 @@ void TestSerialization::runTests(IGameDef *gamedef)
|
|||||||
TEST(testVecPut);
|
TEST(testVecPut);
|
||||||
TEST(testStringLengthLimits);
|
TEST(testStringLengthLimits);
|
||||||
TEST(testBufReader);
|
TEST(testBufReader);
|
||||||
|
TEST(testFloatFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -631,6 +634,75 @@ void TestSerialization::testBufReader()
|
|||||||
UASSERT(!buf.getRawDataNoEx(raw_data, sizeof(raw_data)));
|
UASSERT(!buf.getRawDataNoEx(raw_data, sizeof(raw_data)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestSerialization::testFloatFormat()
|
||||||
|
{
|
||||||
|
FloatType type = getFloatSerializationType();
|
||||||
|
u32 i;
|
||||||
|
f32 fs, fm;
|
||||||
|
|
||||||
|
// Check precision of float calculations on this platform
|
||||||
|
const std::unordered_map<f32, u32> float_results = {
|
||||||
|
{ 0.0f, 0x00000000UL },
|
||||||
|
{ 1.0f, 0x3F800000UL },
|
||||||
|
{ -1.0f, 0xBF800000UL },
|
||||||
|
{ 0.1f, 0x3DCCCCCDUL },
|
||||||
|
{ -0.1f, 0xBDCCCCCDUL },
|
||||||
|
{ 1945329.25f, 0x49ED778AUL },
|
||||||
|
{ -23298764.f, 0xCBB1C166UL },
|
||||||
|
{ 0.5f, 0x3F000000UL },
|
||||||
|
{ -0.5f, 0xBF000000UL }
|
||||||
|
};
|
||||||
|
for (const auto &v : float_results) {
|
||||||
|
i = f32Tou32Slow(v.first);
|
||||||
|
if (std::abs((s64)v.second - i) > 32) {
|
||||||
|
printf("Inaccurate float values on %.9g, expected 0x%X, actual 0x%X\n",
|
||||||
|
v.first, v.second, i);
|
||||||
|
UASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs = u32Tof32Slow(v.second);
|
||||||
|
if (std::fabs(v.first - fs) > std::fabs(v.first * 0.000005f)) {
|
||||||
|
printf("Inaccurate float values on 0x%X, expected %.9g, actual 0x%.9g\n",
|
||||||
|
v.second, v.first, fs);
|
||||||
|
UASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == FLOATTYPE_SLOW) {
|
||||||
|
// conversion using memcpy is not possible
|
||||||
|
// Skip exact float comparison checks below
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto test_single = [&fs, &fm](const u32 &i) -> bool {
|
||||||
|
memcpy(&fm, &i, 4);
|
||||||
|
fs = u32Tof32Slow(i);
|
||||||
|
if (fm != fs) {
|
||||||
|
printf("u32Tof32Slow failed on 0x%X, expected %.9g, actual %.9g\n",
|
||||||
|
i, fm, fs);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (f32Tou32Slow(fs) != i) {
|
||||||
|
printf("f32Tou32Slow failed on %.9g, expected 0x%X, actual 0x%X\n",
|
||||||
|
fs, i, f32Tou32Slow(fs));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use step of prime 277 to speed things up from 3 minutes to a few seconds
|
||||||
|
// Test from 0 to 0xFF800000UL (positive)
|
||||||
|
for (i = 0x00000000UL; i <= 0x7F800000UL; i += 277)
|
||||||
|
UASSERT(test_single(i));
|
||||||
|
|
||||||
|
// Ensure +inf and -inf are tested
|
||||||
|
UASSERT(test_single(0x7F800000UL));
|
||||||
|
UASSERT(test_single(0xFF800000UL));
|
||||||
|
|
||||||
|
// Test from 0x80000000UL to 0xFF800000UL (negative)
|
||||||
|
for (i = 0x80000000UL; i <= 0xFF800000UL; i += 277)
|
||||||
|
UASSERT(test_single(i));
|
||||||
|
}
|
||||||
|
|
||||||
const u8 TestSerialization::test_serialized_data[12 * 13] = {
|
const u8 TestSerialization::test_serialized_data[12 * 13] = {
|
||||||
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
|
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
|
||||||
|
@ -4,6 +4,7 @@ set(UTIL_SRCS
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/base64.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/base64.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/directiontables.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/directiontables.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/enriched_string.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/enriched_string.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/ieee_float.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/serialize.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/serialize.cpp
|
||||||
|
136
src/util/ieee_float.cpp
Normal file
136
src/util/ieee_float.cpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* Conversion of f32 to IEEE-754 and vice versa.
|
||||||
|
*
|
||||||
|
* © Copyright 2018 Pedro Gimeno Fortea.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "ieee_float.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "porting.h"
|
||||||
|
#include <limits>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
// Given an unsigned 32-bit integer representing an IEEE-754 single-precision
|
||||||
|
// float, return the float.
|
||||||
|
f32 u32Tof32Slow(u32 i)
|
||||||
|
{
|
||||||
|
// clang-format off
|
||||||
|
int exp = (i >> 23) & 0xFF;
|
||||||
|
u32 sign = i & 0x80000000UL;
|
||||||
|
u32 imant = i & 0x7FFFFFUL;
|
||||||
|
if (exp == 0xFF) {
|
||||||
|
// Inf/NaN
|
||||||
|
if (imant == 0) {
|
||||||
|
if (std::numeric_limits<f32>::has_infinity)
|
||||||
|
return sign ? -std::numeric_limits<f32>::infinity() :
|
||||||
|
std::numeric_limits<f32>::infinity();
|
||||||
|
return sign ? std::numeric_limits<f32>::max() :
|
||||||
|
std::numeric_limits<f32>::lowest();
|
||||||
|
}
|
||||||
|
return std::numeric_limits<f32>::has_quiet_NaN ?
|
||||||
|
std::numeric_limits<f32>::quiet_NaN() : -0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exp) {
|
||||||
|
// Denormal or zero
|
||||||
|
return sign ? -ldexpf((f32)imant, -149) : ldexpf((f32)imant, -149);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sign ? -ldexpf((f32)(imant | 0x800000UL), exp - 150) :
|
||||||
|
ldexpf((f32)(imant | 0x800000UL), exp - 150);
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a float, return an unsigned 32-bit integer representing the f32
|
||||||
|
// in IEEE-754 single-precision format.
|
||||||
|
u32 f32Tou32Slow(f32 f)
|
||||||
|
{
|
||||||
|
u32 signbit = std::copysign(1.0f, f) == 1.0f ? 0 : 0x80000000UL;
|
||||||
|
if (f == 0.f)
|
||||||
|
return signbit;
|
||||||
|
if (std::isnan(f))
|
||||||
|
return signbit | 0x7FC00000UL;
|
||||||
|
if (std::isinf(f))
|
||||||
|
return signbit | 0x7F800000UL;
|
||||||
|
int exp;
|
||||||
|
f32 mant = frexpf(f, &exp);
|
||||||
|
u32 imant = (u32)std::floor((signbit ? -16777216.f : 16777216.f) * mant);
|
||||||
|
exp += 126;
|
||||||
|
if (exp <= 0) {
|
||||||
|
// Denormal
|
||||||
|
return signbit | (exp <= -31 ? 0 : imant >> (1 - exp));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp >= 255) {
|
||||||
|
// Overflow due to the platform having exponents bigger than IEEE ones.
|
||||||
|
// Return signed infinity.
|
||||||
|
return signbit | 0x7F800000UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regular number
|
||||||
|
return signbit | (exp << 23) | (imant & 0x7FFFFFUL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test needs the following requisites in order to work:
|
||||||
|
// - The float type must be a 32 bits IEEE-754 single-precision float.
|
||||||
|
// - The endianness of f32s and integers must match.
|
||||||
|
FloatType getFloatSerializationType()
|
||||||
|
{
|
||||||
|
// clang-format off
|
||||||
|
const f32 cf = -22220490.f;
|
||||||
|
const u32 cu = 0xCBA98765UL;
|
||||||
|
if (std::numeric_limits<f32>::is_iec559 && sizeof(cf) == 4 &&
|
||||||
|
sizeof(cu) == 4 && !memcmp(&cf, &cu, 4)) {
|
||||||
|
// u32Tof32Slow and f32Tou32Slow are not needed, use memcpy
|
||||||
|
return FLOATTYPE_SYSTEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run quick tests to ensure the custom functions provide acceptable results
|
||||||
|
warningstream << "floatSerialization: f32 and u32 endianness are "
|
||||||
|
"not equal or machine is not IEEE-754 compliant" << std::endl;
|
||||||
|
u32 i;
|
||||||
|
char buf[128];
|
||||||
|
|
||||||
|
// NaN checks aren't included in the main loop
|
||||||
|
if (!std::isnan(u32Tof32Slow(0x7FC00000UL))) {
|
||||||
|
porting::mt_snprintf(buf, sizeof(buf),
|
||||||
|
"u32Tof32Slow(0x7FC00000) failed to produce a NaN, actual: %.9g",
|
||||||
|
u32Tof32Slow(0x7FC00000UL));
|
||||||
|
infostream << buf << std::endl;
|
||||||
|
}
|
||||||
|
if (!std::isnan(u32Tof32Slow(0xFFC00000UL))) {
|
||||||
|
porting::mt_snprintf(buf, sizeof(buf),
|
||||||
|
"u32Tof32Slow(0xFFC00000) failed to produce a NaN, actual: %.9g",
|
||||||
|
u32Tof32Slow(0xFFC00000UL));
|
||||||
|
infostream << buf << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = f32Tou32Slow(std::numeric_limits<f32>::quiet_NaN());
|
||||||
|
// check that it corresponds to a NaN encoding
|
||||||
|
if ((i & 0x7F800000UL) != 0x7F800000UL || (i & 0x7FFFFFUL) == 0) {
|
||||||
|
porting::mt_snprintf(buf, sizeof(buf),
|
||||||
|
"f32Tou32Slow(NaN) failed to encode NaN, actual: 0x%X", i);
|
||||||
|
infostream << buf << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FLOATTYPE_SLOW;
|
||||||
|
// clang-format on
|
||||||
|
}
|
34
src/util/ieee_float.h
Normal file
34
src/util/ieee_float.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
Minetest
|
||||||
|
Copyright (C) 2018 SmallJoker <mk939@ymail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "irrlichttypes.h"
|
||||||
|
|
||||||
|
enum FloatType
|
||||||
|
{
|
||||||
|
FLOATTYPE_UNKNOWN,
|
||||||
|
FLOATTYPE_SLOW,
|
||||||
|
FLOATTYPE_SYSTEM
|
||||||
|
};
|
||||||
|
|
||||||
|
f32 u32Tof32Slow(u32 i);
|
||||||
|
u32 f32Tou32Slow(f32 f);
|
||||||
|
|
||||||
|
FloatType getFloatSerializationType();
|
@ -28,6 +28,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
FloatType g_serialize_f32_type = FLOATTYPE_UNKNOWN;
|
||||||
|
|
||||||
////
|
////
|
||||||
//// BufReader
|
//// BufReader
|
||||||
////
|
////
|
||||||
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "irrlichttypes_bloated.h"
|
#include "irrlichttypes_bloated.h"
|
||||||
#include "exceptions.h" // for SerializationError
|
#include "exceptions.h" // for SerializationError
|
||||||
#include "debug.h" // for assert
|
#include "debug.h" // for assert
|
||||||
|
#include "ieee_float.h"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#if HAVE_ENDIAN_H
|
#if HAVE_ENDIAN_H
|
||||||
@ -60,6 +61,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#define LONG_STRING_MAX_LEN (64 * 1024 * 1024)
|
#define LONG_STRING_MAX_LEN (64 * 1024 * 1024)
|
||||||
|
|
||||||
|
|
||||||
|
extern FloatType g_serialize_f32_type;
|
||||||
|
|
||||||
#if HAVE_ENDIAN_H
|
#if HAVE_ENDIAN_H
|
||||||
// use machine native byte swapping routines
|
// use machine native byte swapping routines
|
||||||
// Note: memcpy below is optimized out by modern compilers
|
// Note: memcpy below is optimized out by modern compilers
|
||||||
@ -188,6 +191,25 @@ inline f32 readF1000(const u8 *data)
|
|||||||
return (f32)readS32(data) / FIXEDPOINT_FACTOR;
|
return (f32)readS32(data) / FIXEDPOINT_FACTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline f32 readF32(const u8 *data)
|
||||||
|
{
|
||||||
|
u32 u = readU32(data);
|
||||||
|
|
||||||
|
switch (g_serialize_f32_type) {
|
||||||
|
case FLOATTYPE_SYSTEM: {
|
||||||
|
f32 f;
|
||||||
|
memcpy(&f, &u, 4);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
case FLOATTYPE_SLOW:
|
||||||
|
return u32Tof32Slow(u);
|
||||||
|
case FLOATTYPE_UNKNOWN: // First initialization
|
||||||
|
g_serialize_f32_type = getFloatSerializationType();
|
||||||
|
return readF32(data);
|
||||||
|
}
|
||||||
|
throw SerializationError("readF32: Unreachable code");
|
||||||
|
}
|
||||||
|
|
||||||
inline video::SColor readARGB8(const u8 *data)
|
inline video::SColor readARGB8(const u8 *data)
|
||||||
{
|
{
|
||||||
video::SColor p(readU32(data));
|
video::SColor p(readU32(data));
|
||||||
@ -245,6 +267,15 @@ inline v3f readV3F1000(const u8 *data)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline v3f readV3F32(const u8 *data)
|
||||||
|
{
|
||||||
|
v3f p;
|
||||||
|
p.X = (float)readF32(&data[0]);
|
||||||
|
p.Y = (float)readF32(&data[4]);
|
||||||
|
p.Z = (float)readF32(&data[8]);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
/////////////// write routines ////////////////
|
/////////////// write routines ////////////////
|
||||||
|
|
||||||
inline void writeU8(u8 *data, u8 i)
|
inline void writeU8(u8 *data, u8 i)
|
||||||
@ -278,6 +309,23 @@ inline void writeF1000(u8 *data, f32 i)
|
|||||||
writeS32(data, i * FIXEDPOINT_FACTOR);
|
writeS32(data, i * FIXEDPOINT_FACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void writeF32(u8 *data, f32 i)
|
||||||
|
{
|
||||||
|
switch (g_serialize_f32_type) {
|
||||||
|
case FLOATTYPE_SYSTEM: {
|
||||||
|
u32 u;
|
||||||
|
memcpy(&u, &i, 4);
|
||||||
|
return writeU32(data, u);
|
||||||
|
}
|
||||||
|
case FLOATTYPE_SLOW:
|
||||||
|
return writeU32(data, f32Tou32Slow(i));
|
||||||
|
case FLOATTYPE_UNKNOWN: // First initialization
|
||||||
|
g_serialize_f32_type = getFloatSerializationType();
|
||||||
|
return writeF32(data, i);
|
||||||
|
}
|
||||||
|
throw SerializationError("writeF32: Unreachable code");
|
||||||
|
}
|
||||||
|
|
||||||
inline void writeARGB8(u8 *data, video::SColor p)
|
inline void writeARGB8(u8 *data, video::SColor p)
|
||||||
{
|
{
|
||||||
writeU32(data, p.color);
|
writeU32(data, p.color);
|
||||||
@ -322,6 +370,13 @@ inline void writeV3F1000(u8 *data, v3f p)
|
|||||||
writeF1000(&data[8], p.Z);
|
writeF1000(&data[8], p.Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void writeV3F32(u8 *data, v3f p)
|
||||||
|
{
|
||||||
|
writeF32(&data[0], p.X);
|
||||||
|
writeF32(&data[4], p.Y);
|
||||||
|
writeF32(&data[8], p.Z);
|
||||||
|
}
|
||||||
|
|
||||||
////
|
////
|
||||||
//// Iostream wrapper for data read/write
|
//// Iostream wrapper for data read/write
|
||||||
////
|
////
|
||||||
@ -351,12 +406,14 @@ MAKE_STREAM_READ_FXN(s16, S16, 2);
|
|||||||
MAKE_STREAM_READ_FXN(s32, S32, 4);
|
MAKE_STREAM_READ_FXN(s32, S32, 4);
|
||||||
MAKE_STREAM_READ_FXN(s64, S64, 8);
|
MAKE_STREAM_READ_FXN(s64, S64, 8);
|
||||||
MAKE_STREAM_READ_FXN(f32, F1000, 4);
|
MAKE_STREAM_READ_FXN(f32, F1000, 4);
|
||||||
|
MAKE_STREAM_READ_FXN(f32, F32, 4);
|
||||||
MAKE_STREAM_READ_FXN(v2s16, V2S16, 4);
|
MAKE_STREAM_READ_FXN(v2s16, V2S16, 4);
|
||||||
MAKE_STREAM_READ_FXN(v3s16, V3S16, 6);
|
MAKE_STREAM_READ_FXN(v3s16, V3S16, 6);
|
||||||
MAKE_STREAM_READ_FXN(v2s32, V2S32, 8);
|
MAKE_STREAM_READ_FXN(v2s32, V2S32, 8);
|
||||||
MAKE_STREAM_READ_FXN(v3s32, V3S32, 12);
|
MAKE_STREAM_READ_FXN(v3s32, V3S32, 12);
|
||||||
MAKE_STREAM_READ_FXN(v2f, V2F1000, 8);
|
MAKE_STREAM_READ_FXN(v2f, V2F1000, 8);
|
||||||
MAKE_STREAM_READ_FXN(v3f, V3F1000, 12);
|
MAKE_STREAM_READ_FXN(v3f, V3F1000, 12);
|
||||||
|
MAKE_STREAM_READ_FXN(v3f, V3F32, 12);
|
||||||
MAKE_STREAM_READ_FXN(video::SColor, ARGB8, 4);
|
MAKE_STREAM_READ_FXN(video::SColor, ARGB8, 4);
|
||||||
|
|
||||||
MAKE_STREAM_WRITE_FXN(u8, U8, 1);
|
MAKE_STREAM_WRITE_FXN(u8, U8, 1);
|
||||||
@ -368,12 +425,14 @@ MAKE_STREAM_WRITE_FXN(s16, S16, 2);
|
|||||||
MAKE_STREAM_WRITE_FXN(s32, S32, 4);
|
MAKE_STREAM_WRITE_FXN(s32, S32, 4);
|
||||||
MAKE_STREAM_WRITE_FXN(s64, S64, 8);
|
MAKE_STREAM_WRITE_FXN(s64, S64, 8);
|
||||||
MAKE_STREAM_WRITE_FXN(f32, F1000, 4);
|
MAKE_STREAM_WRITE_FXN(f32, F1000, 4);
|
||||||
|
MAKE_STREAM_WRITE_FXN(f32, F32, 4);
|
||||||
MAKE_STREAM_WRITE_FXN(v2s16, V2S16, 4);
|
MAKE_STREAM_WRITE_FXN(v2s16, V2S16, 4);
|
||||||
MAKE_STREAM_WRITE_FXN(v3s16, V3S16, 6);
|
MAKE_STREAM_WRITE_FXN(v3s16, V3S16, 6);
|
||||||
MAKE_STREAM_WRITE_FXN(v2s32, V2S32, 8);
|
MAKE_STREAM_WRITE_FXN(v2s32, V2S32, 8);
|
||||||
MAKE_STREAM_WRITE_FXN(v3s32, V3S32, 12);
|
MAKE_STREAM_WRITE_FXN(v3s32, V3S32, 12);
|
||||||
MAKE_STREAM_WRITE_FXN(v2f, V2F1000, 8);
|
MAKE_STREAM_WRITE_FXN(v2f, V2F1000, 8);
|
||||||
MAKE_STREAM_WRITE_FXN(v3f, V3F1000, 12);
|
MAKE_STREAM_WRITE_FXN(v3f, V3F1000, 12);
|
||||||
|
MAKE_STREAM_WRITE_FXN(v3f, V3F32, 12);
|
||||||
MAKE_STREAM_WRITE_FXN(video::SColor, ARGB8, 4);
|
MAKE_STREAM_WRITE_FXN(video::SColor, ARGB8, 4);
|
||||||
|
|
||||||
////
|
////
|
||||||
|
Loading…
Reference in New Issue
Block a user