Quaternion bug?

Sorry, I forgot the word “final”. In JogAmp’s Ardor3D Continuation and earlier in the legacy Ardor3D, Quaternion implements ReadOnlyQuaternion, IDENTITY is a ReadOnlyQuaternion. If a stupid programmer wants to modify IDENTITY, he must use a cast.

There is no perfect solution but Ardor3D’s one seems to be less error prone to me.

1 Like

Well I’m with @pspeed on this. Object constants in java are like this. if you use their references for anything else than reading you’ll get caught… That’s something every Java programmer should know, so I consider this almost educational.

There is nothing to fix here… just some basics to know on the developer side.

2 Likes

Seems like a perfect solution would be to get rid of the IDENTITY constant in this case… since it provides no real value at all.

2 Likes

this change will break back compatibility…

1 Like

…as would changing it to be some new interface.

Of all of the unworkable solutions that will cause more problems than they are worth… the path to removing the IDENTITY constant is the best one.

Deprecate it now. Put a big comment that you are silly to use it and why. Remove it some time in the future.

Then the conversation will just switch to the “problems” with the Vector3f constants. Which actually do have valid use-cases and we also won’t be “fixing”.

2 Likes

I don’t consider these problems like real problems… These constants are ok for java developers, if someone doesn’t understand java language, it’s his own problem.

1 Like

instead just do new Quaternion() for me this sounds like a perfect solution AND I guess if everybody does replace the constant by better solution, some nasty bugs suddenly vanish :wink:

1 Like

Have you ever found one object exposed in the standard JavaSE API considered as something that mustn’t mutate but that you can modify anyway trivially? I’ve just looked at Vecmath, there is no IDENTITY Vector3f, it’s similar to @ia97lies 's suggestion.

As far as I know, the “final” keyword ensures that you cannot replace a reference by another one, it doesn’t ensure that the referenced object won’t mutate.

1 Like

Well maybe java SE doesn’t do it but I’ve seen it many times in many APIs. But even if it was a JME only thing, the issue is so easily circumvented that IMO it doesn’t worse the hassle of making a read only quaternion.

3 Likes

The thing is, someone who doesn’t get this will also be confused by multi() vs multLocal on Vectors. Personally I like that idea, since you can a) pass a vector instead of only a “position” (the vector can change over time) and b) you have full control about when you want to create a copy.

I mean, actually it’s really easy to just use:

a.mult(b).addLocal(c).multLocal(d).subLocal(f);

If you don’t want to destroy a you use multi the first time and then you have a “throw away” vector.

And things like a == Vector3f.ZERO are wrong anyway, and a.equals(Vector3f.ZERO) are also at least dubious.

Maybe we should cover this in the Tutorials then?

1 Like

JogAmp’s Ardor3D Continuation has the same kind of methods to modify “on place” the caller but @Murph9 's problem can hardly happen with this engine as com.ardor3d.math.Vector3.UNIT_Y uses the read-only interface ReadOnlyVector3. If you put UNIT_Y into a variable and if you modify it in JMonkeyEngine 3, you won’t see that you’ll modify an object that is intended to remain unchanged, it’s a not a matter of Java language understanding.

1 Like

using interfaces in hot places isn’t good practice.

1 Like

In order for this to work some things would also have to be done:
Either:

  1. add a whole separate set of Vector3f methods that take this interface thus doubling the maintenance load of Vector3f.
  2. redo all of the methods that take Vector3f to take the read-only interface and modify them to call getX(), getY(), etc. instead of accessing the fields directly… ie: slow down every single one of these methods significantly (at least double but likely more).

For an error that relatively speaking almost no one ever makes and most who do are going to stumble in 100 different areas anyway. It’s just totally not worth it. Like, not even close to worth it.

And that is easily fixed with a TotalNoobAppState that just checks the “constants” once a frame to see if you’ve screwed them up.

With that, at least the less experienced developers would have a safety net for the 1 out of 1000 pitfalls they will hit and everyone else will have something they can quickly add to check if they screwed up… then remove it and get on with their day.

1 Like

Where have you read that using interfaces in hot places isn’t a good practice? If you prefer not using an interface here to preserve the performance, have you ever tried to measure the real impact of such a change?

@pspeed You wouldn’t need to add a whole separate set of Vector3f methods, you would need to replace Vector3f by its read-only counterpart in the return types and in the parameters when a real-only instance is expected and I doubt that using accessors would cause an important slow down especially in desktop environments. Some micro-benchmarks contradict your comment but maybe I’m completely wrong:
https://stackoverflow.com/a/24117737

I don’t think that you spend your life in modifying maths classes, JMonkeyEngine 3 isn’t a linear algebra library.

2 Likes

I already said this alternative which is also a non-starter. Doubling the time of core methods is not high on my to-do list.

1 Like

I mean… it’s logical. Even the byte code will say that a field access is going to be WAAAAAAAAY faster than a polymorphic method lookup, plus a method call, plus a field access. I mean, you do one thing instead of three things.

…and the method lookup is going to kill you. That interface could be anything.

1 Like

It’s logical that using a method instead of a field has a cost but you claim that it would double the cost without any evidence.

1 Like

At least double. When you do two things instead of one thing and both of those things are similar. Calling a method to access a field ALSO requires looking up a field. So at least double.

But if we break it down, from an access perspective a field access is going to be faster than a method access. Method lookups require a more expensive lookup because the method could be defined on different classes… it’s a polymorphic lookup. Fields cannot be overridden and so the proper class was resolved at compile time.

But even aside from the lookups. In one case, you have a byte code to retrieve a field. In the other case, you have a byte code to invoke a method that will then have a byte code to retrieve a field. Having been in the JVM code many times, I cannot possibly imagine how a field access would be SLOWER than a method access.

Therefore, logically, the method is at best the same timing as a field access… ie: method + field access is at best double field access alone.

All together it’s probably at least 3 or 4 times… but double is safe to say.

2 Likes