From bfcd78c43e88d513fafdd7c4633d0857bdcf5fb1 Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Mon, 25 Sep 2023 13:43:59 -0500 Subject: [PATCH] Round decimal place in Vector3 and CFrame when converting to dom type --- CHANGELOG.md | 1 + src/roblox/datatypes/mod.rs | 2 ++ src/roblox/datatypes/types/vector3.rs | 11 +++++++---- src/roblox/datatypes/util.rs | 16 ++++++++++++++++ 4 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 src/roblox/datatypes/util.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 25234ed..5cf906d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Update to Luau version `0.594` +- CFrame and Vector3 values are now rounded to the nearest 2 ^ 16 decimal place to reduce floating point errors and diff noise. Note that this does not affect intermediate calculations done in lua, and only happens when a property value is set on an Instance. ### Fixed diff --git a/src/roblox/datatypes/mod.rs b/src/roblox/datatypes/mod.rs index 6604d5f..5432c50 100644 --- a/src/roblox/datatypes/mod.rs +++ b/src/roblox/datatypes/mod.rs @@ -6,6 +6,8 @@ pub mod extension; pub mod result; pub mod types; +mod util; + use result::*; pub use crate::roblox::shared::userdata::*; diff --git a/src/roblox/datatypes/types/vector3.rs b/src/roblox/datatypes/types/vector3.rs index a7ba383..ef0307e 100644 --- a/src/roblox/datatypes/types/vector3.rs +++ b/src/roblox/datatypes/types/vector3.rs @@ -5,7 +5,10 @@ use glam::Vec3; use mlua::prelude::*; use rbx_dom_weak::types::Vector3 as DomVector3; -use crate::{lune::util::TableBuilder, roblox::exports::LuaExportsTable}; +use crate::{ + lune::util::TableBuilder, + roblox::{datatypes::util::round_float_decimal, exports::LuaExportsTable}, +}; use super::{super::*, EnumItem}; @@ -212,9 +215,9 @@ impl From for Vector3 { impl From for DomVector3 { fn from(v: Vector3) -> Self { DomVector3 { - x: v.0.x, - y: v.0.y, - z: v.0.z, + x: round_float_decimal(v.0.x), + y: round_float_decimal(v.0.y), + z: round_float_decimal(v.0.z), } } } diff --git a/src/roblox/datatypes/util.rs b/src/roblox/datatypes/util.rs new file mode 100644 index 0000000..7855507 --- /dev/null +++ b/src/roblox/datatypes/util.rs @@ -0,0 +1,16 @@ +// HACK: We round to the nearest Very Small Decimal +// to reduce writing out floating point accumulation +// errors to files (mostly relevant for xml formats) +const ROUNDING: usize = 65_536; // 2 ^ 16 + +pub fn round_float_decimal(value: f32) -> f32 { + let place = ROUNDING as f32; + + // Round only the fractional part, we do not want to + // lose any float precision in case a user for some + // reason has very very large float numbers in files + let whole = value.trunc(); + let fract = (value.fract() * place).round() / place; + + whole + fract +}