Code Monkey home page Code Monkey logo

Comments (13)

GITHUB243884919 avatar GITHUB243884919 commented on June 28, 2024

And i found Debug.LogError(new F64(1.3d) + new F64(0.1d)); result is 1.39999999967404

from fixpointcs.

petrikero avatar petrikero commented on June 28, 2024

Can you provide the calculations that outputted the undesired F64Vec3 you mentioned?

In general, the fixed points (nor floating points in Unity vectors) cannot produce all values exactly correctly. Unity rounds its vectors to only a few decimal places when printing them out, which makes it look like they might actually be exactly accurate (like your example of 1.3 + 0.1 == 1.4), when they're actually not.

The included vector library doesn't do such aggressive rounding, which is the reason why you are seeing the different results. You can modify the ToString() methods to output fewer decimals, if you wish to match Unity's behavior more closely.

That being said, there will always be some differences in results when comparing Unity and FixPointCS, as Unity's vectors use floats. This is by design.

from fixpointcs.

GITHUB243884919 avatar GITHUB243884919 commented on June 28, 2024

1 step :I write 2 functions
(1)For rotate a vector rotate by y-axle
public static F64Vec3 RotateY(F64Vec3 lhs, F64 angle)
{
F64 rad = F64.DegToRad2(angle);
F64 cos = F64.Cos(rad);
F64 sin = F64.Sin(rad);
F64 x = lhs.X * cos + lhs.Z * sin;
F64 y = lhs.Y;
F64 z = -lhs.X * sin + lhs.Z * cos;

return new F64Vec3(x, y, z);

}

(2)For convert a point's pos in world space to local space.
Local space's o is param o, x-axle is param forward, y-axle is param left.
And forward, left is unit vector, and they are all in world space.
public static F64Vec3 PointToLocalSpace2D(F64Vec3 p, F64Vec3 forward, F64Vec3 left, F64Vec3 o)
{
var p2 = new F64Vec2(p.X, p.Z);
var f2 = new F64Vec2(forward.X, forward.Z);
var l2 = new F64Vec2(left.X, left.Z);
var o2 = new F64Vec2(o.X, o.Z);
var X = F64Vec2.Dot(f2, p2) - F64Vec2.Dot(o2, f2);
var Y = F64Vec2.Dot(l2, p2) - F64Vec2.Dot(o2, l2);
return new F64Vec3(X, p.Y, Y);
}

2 step
A tank's pos (0, 0, 0) forward is F64Vec3(0, 0, 1),
left is F64Vec3.RotateY(forward, new FixMath.F64(-90)).
They are all in world space.
I do 3 loop, tank RotateY 30, and move 5. code is follow
for (int i = 0; i < 3; i++)
{
F64Vec3 newDir = F64Vec3.RotateY(obj.GetDir(), new F64(30));
obj.SetDir(F64Vec3.Normalize(newDir));
obj.SetPos(obj.GetPos() + (newDir * new F64(5)));
tankGo.transform.position = obj.GetPos().ToUnityVector3();
tankGo.transform.forward = obj.GetDir().ToUnityVector3();
GameObject.Instantiate(tankGo);
}
Debug.LogError("Tank " + obj.GetPos() + " " + obj.GetPos().ToUnityVector3());
in this code, tank is obj.

3 step
a sphere pos is (x=obj.x, z=obj.z + 1.4), and convert pos to tank's local space.
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
F64 radius = F64.Half;
//F64 foffsetX = F64.One;
F64 foffsetX = F64.Zero;
//F64 foffsetZ = obj.moveData.detectionWidth + radius + new F64(-0.1);
F64 foffsetZ = F64.FromFloat(1.4f);
F64Vec3 fcubePos = new F64Vec3(obj.GetPos().X + foffsetX, obj.GetPos().Y, obj.GetPos().Z + foffsetZ);
sphere.transform.position = fcubePos.ToUnityVector3();
F64Vec3 flocalCube = F64Vec3.PointToLocalSpace2D(fcubePos,
obj.forward, obj.left, obj.GetPos());

Debug.LogError("Sphere pos in tank's local space " + flocalCube + " " + flocalCube.ToUnityVector3());
I think Sphere's pos in tank's local space is (0.0, 0.0, 1.4)
but now is (-1.93249434232712E-08, 0, 1.39999999897555)
if i use ToUnityVector3, result is (0.0, 0.0, 1.4)
public Vector3 ToUnityVector3()
{
return new Vector3(X.Float, Y.Float, Z.Float);
}

I know why z is 1.39999999897555 and not 1.4
but i do not know why x = -1.93249434232712E-08 and not 0.
Maybe they are in same reason.
Maybe 1.93249434232712E-08 is approximate 0.
I know unity has a function Mathf.Approximately(float a, float b)
I think maybe F64 should has a function like that.

from fixpointcs.

GITHUB243884919 avatar GITHUB243884919 commented on June 28, 2024

I have a project in https://github.com/GITHUB243884919/unity_study2019.git
if you need to debug. test scene is local
Assets/UFrame/Scenes/TestFx.unity
The Main Camera in this scene has a script. TestFix.cs
there is a function void TestFCS_P(), and it in TestFix's Start function

from fixpointcs.

GITHUB243884919 avatar GITHUB243884919 commented on June 28, 2024

And PointCS has
public static F64 DegToRad(F64 a) { return FromRaw(Fixed64.Mul(a.Raw, 74961320)); } // F64.Pi / 180
my code is
public static F64 DegToRad2(F64 a) { return a * Pi / F180; }
public static F64 F180 = new F64(180);
I think maybe DegToRad2 can get batter precision than DegToRad

from fixpointcs.

petrikero avatar petrikero commented on June 28, 2024

It looks to me like you're doing some fairly complex arithmetic with multiple rotations and expecting to get precise results. This isn't really the case with either fixed point or floating point, as both of them can only provide approximately correct answers, not exactly precise in the general case, especially when angles and rotations are involved.

If you want to get behavior closer to Unity's, you can add the Approximately() function you mentioned. I'm reluctant to add this to the official version, though, as it's quite application-specific what constitutes close enough to be approximately same. I believe Unity even allows for some amount of error in its Vector3==() operator.

I'd need a fully self-contained test case in order to take a look at this further: a single function demonstrating the problem with no outside arguments or dependencies on external software like Unity.

Also, it may be that your version of DegToRad() is somewhat more precise, perhaps giving you even exactly correct results in this case, but it's also a lot slower due to the full resolution F64 division. But again, if this is the behavior that you prefer, feel free to modify your copy of F64, that's precisely how the library is meant to be used!

from fixpointcs.

petrikero avatar petrikero commented on June 28, 2024

Oh, I just realized I had overlooked this sentence: "Maybe 1.93249434232712E-08 is approximate 0."

The E-notation means that x is an extremely small number, 1.93249 * 10^-8, or 0.0000000193429, so the value is indeed very close to zero.

Maybe this answers your question?

from fixpointcs.

GITHUB243884919 avatar GITHUB243884919 commented on June 28, 2024

Thank you very very very much! Thank for you answer, I got~ Now I know DegToRad2 is not batter than DegToRad. About precision, I think Unity has same problems, so they provide Approximately(a, b)。FixPointCS and my arithmetic are both right。 I review Unity's documents. about Mathf.Approximately. I found it have a value Mathf.Epsilon. I copy it's document. I really like FixPointCS , and I really need a value just like Unity's Epsilon. Because I really need some do some logic code , these code must know some things just like (-1.93249434232712E-08, 0, 1.39999999897555) just is (0, 0, 1.4). Can you help me ~ thank you~ i need Approximately and Epsilon for FixPointCS

Mathf.Approximately
Compares two floating point values and returns true if they are similar.
Floating point imprecision makes comparing floats using the equals operator inaccurate. For example, (1.0 == 10.0 / 10.0) might not return true every time. Approximately() compares two floats and returns true if they are within a small value (Epsilon) of each other.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mathf.Epsilon 
A tiny floating point value (Read Only).
The smallest value that a float can have different from zero.
With the following rules:
- anyValue + Epsilon = anyValue
- anyValue - Epsilon = anyValue
- 0 + Epsilon = Epsilon
- 0 - Epsilon = -Epsilon
~~~~~~~~~~~~~~~~~~~~~~

 

from fixpointcs.

GITHUB243884919 avatar GITHUB243884919 commented on June 28, 2024

https://docs.unity3d.com/ScriptReference/Mathf.Approximately.html
https://docs.unity3d.com/ScriptReference/Mathf.Epsilon.html
these are Unity's document for Approximately and Epsilon

using UnityEngine;

public class Example : MonoBehaviour
{
// Compares two floating point numbers and return true if they are the same number.
// See also Mathf.Approximately, which compares floating point numbers so you dont have
// to create a function to compare them.

bool isEqual(float a, float b)
{
    if (a >= b - Mathf.Epsilon && a <= b + Mathf.Epsilon)
    {
        return true;
    }
    else
    {
        return false;
    }
}

}

from fixpointcs.

petrikero avatar petrikero commented on June 28, 2024

The concept of Epsilon doesn't behave the same in fixed point, so you can't implement the same semantics as Unity's epsilon has. Any fixed point value other than zero added to another fixed point value will always change it. The reason for this is that fixed point addition is identical to integer addition, the inputs and outputs are just interpreted differently.

You can implement an approximating equality comparison along the lines of:

    public static bool ApproximatelyEqual(F64 a, F64 b)
    {
        return Fixed64.Abs(a.Raw - b.Raw) <= 256;
    }

You can tweak the epsilon value (256) to fit your needs. There's no general formula how it should be set.

I'm closing this issue as it isn't a problem in FixPointCS.

from fixpointcs.

GITHUB243884919 avatar GITHUB243884919 commented on June 28, 2024

thanks for your help ! I know 256 is a very small number in F64, but I do not know why is 256 ? And I guess 128 is that value in F32. May I think 256 >>32 just is precision in F64 ? I think I need review how to use binary to represent float :) Long time ago , when I was a student, I have learned it:)

from fixpointcs.

petrikero avatar petrikero commented on June 28, 2024

No particular reason, it's just a small number. You can try tweaking it to fit your use case (try doubling or halving it until you get the effect you want).

That being said, comparing numbers for rough equality is a bit subject, in my opinion. You'll probably get it to work nicely for most of the time, but, depending on the use case, it can be impossible to get it to work robustly all the time.

from fixpointcs.

GITHUB243884919 avatar GITHUB243884919 commented on June 28, 2024

ok ~ thanks ~

from fixpointcs.

Related Issues (10)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.