Wierd bug with Vector3f

It seems I have uncovered something weird. Two different console outputs for

System.out.println("Vector3f.UNIT_Z = " + Vector3f.UNIT_Z.toString());

Here are the pictures:
Correct output:

Incorrect output:

I had noticed on previous occasions that rotating doors in my project would open on a horizontal axis (X-axis) but could not work out why. So this has been happening very rarely but for some time.

Maybe it’s an influence from an alternate universe!

Are you positive you don’t modify it’s value somewhere in your code?

You have definitely modified UNIT_Z somewhere in your code. Most likely, given the value, you’ve passed it to something that is then using it as a local storage for a vector and then setting it to 1,0,0. There are a couple bad practices in there though it’s hard to decide which one is more dangerous until you locate the issue.

Being able to modify a constant Vector really is bad practice. Wouldn’t it be easier to have Vertor modified so that Vector3f.ZERO returns a Vector wrapper with the setters disabled? Like the unmodifyable collections in the JDK…

@SteveDay said: Being able to modify a constant Vector really is bad practice. Wouldn't it be easier to have Vertor modified so that Vector3f.ZERO returns a Vector wrapper with the setters disabled? Like the unmodifyable collections in the JDK...

There are about a dozen reasons this would be a horrible idea… just to save a few developers from a relatively easily avoided mistake. Whenever there is a case where JME could either hold your hand or be efficient… it chooses efficient. It’s not meant for beginners, really, despite its friendly appearance.

FOUND IT !!

I placed a multitude of println statements in what appeared to be the offending class. I managed to isolate where the problem is occurring and I have fixed it in my own code. I have reproduced a code snippet that causes the same problem and have posted a screen shot of it below. I would like to see if anyone can isolate where the problem is occurring and then tell me why. Here is the pic:

You can see the console output to verify that the object modification has taken place.

Merry Christmas Monkeys !!

This:

Vector3f rotationAxis = Vector3f.UNIT_Z

does not make a copy of the UNIT_Z vector. It is just a pointer reference.

Then

http://hub.jmonkeyengine.org/javadoc/com/jme3/math/Quaternion.html#toAngleAxis(com.jme3.math.Vector3f)

stores the angle axis result in UNIT_Z through the pointer reference.

So it wasn’t an influence from an alternate universe ??? Oh dear … how sad … never mind.

Thank you Mr Maasing. You hit the nail on the head.

I guess this error came about from a few misunderstandings, which are probably prevalent among us common-garden-variety java programmers.

Firstly, we are led to believe that a constant (public static final object (or primative)) is immutable and will throw a compile-time error when trying to compile code that has reassignments to vars declared final.
See …
http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
Scroll down to the Constants paragraph. It specifically says … “constants defined in this way cannot be reassigned”. Well … the truth is … they can! We can do it !! We have the power !!

Secondly, I find the Quaternion class in jME3 kinda confusing. Quaternions are hard to grasp anyway and it’s not the first time I have run into problems with the class, I have other posts regarding it. I was looking for a method that would take in a vector3f as a rotation-axis vector and return the float value in radians of where the spatial’s quaternion had rotated on that axis. I chose the wrong method to call. But the funny thing is that it has worked fine up until now. I would like to use a method that will give me the info I want, so suggestions are open. Maybe the one that returns a float[] will work ok, since I only need to get the angle for one axis anyway, the x-axis would probably suffice.

Thirdly … and lastly … I find it counter intuitive to pass in an object to a method where the parameter object itself will be modified. I thought that was the general idea behind returning an object from a method. Is this a way to return more from a method than just one variable? I must admit that I had to read the javadoc for that method several times before I caught onto the idea that the vector passed in was being written to … after reading Mr Maasing’s explanation. I have also seen methods there that do both … goodness knows why … writing to the parameter object passed in and returning the same object as a method return.

It is a learning experience. Life is good.

@alfinete said: So it wasn't an influence from an alternate universe !!?? Oh dear ... how sad ... never mind.

Thank you Mr Maasing. You hit the nail on the head.

I guess this error came about from a few misunderstandings, which are probably prevalent among us common-garden-variety java programmers.

Firstly, we are led to believe that a constant (public static final object (or primative)) is immutable and will throw a compile-time error when trying to compile code that has reassignments to vars declared final.
See …
Understanding Class Members (The Java™ Tutorials > Learning the Java Language > Classes and Objects)
Scroll down to the Constants paragraph. It specifically says … “constants defined in this way cannot be reassigned”. Well … the truth is … they can! We can do it !! We have the power !!

No, you can’t reassign THE REFERENCE. You can do whatever you want to the OBJECT itself. This is pretty basic Java stuff that most of us hit in the first 6 months of using Java. So, you can’t say Vector3f.UNIT_Z = new Vector3f()… but you can certainly modify its internal data.

Java doesn’t have the concept of C++ const modifier. On the one hand, it’s a shame. On the other hand, it would be a real pain for other reasons.

@alfinete said: Secondly, I find the Quaternion class in jME3 kinda confusing. Quaternions are hard to grasp anyway and it's not the first time I have run into problems with the class, I have other posts regarding it. I was looking for a method that would take in a vector3f as a rotation-axis vector and return the float value in radians of where the spatial's quaternion had rotated on that axis. I chose the wrong method to call. But the funny thing is that it has worked fine up until now. I would like to use a method that will give me the info I want, so suggestions are open. Maybe the one that returns a float[] will work ok, since I only need to get the angle for one axis anyway, the x-axis would probably suffice.

You can’t do what you are asking for. You cannot take an arbitrary rotation and turn it into “whatever axis you want” rotated… because it’s impossible. A Quaternion can be turned into an angle + axis but both are specific to the particular quaternion.

If only people knew where the javadoc was since the parameter is clearly called:
toAngleAxis(Vector3f axisStore)

axis STORE… as in the place where the AXIS will be STORED.

Not to mention that the more detailed Javadoc specifically says this:
http://hub.jmonkeyengine.org/javadoc/com/jme3/math/Quaternion.html#toAngleAxis(com.jme3.math.Vector3f)

Seriously folks, if you do not have the javadoc open or just one click away then go ahead and hang up your Java-programmer badge right now and find something else to do. :wink: Coming from the C/C++ world of yesteryear, Javadoc was a HUGE boon because at the time C/C++ had nothing like that. Suddenly, all information was laid bare and only a few clicks away and I find extremely painful that the collective would prefer to bumble along without it.

…though I guess it looks like you DID look at it. So many don’t and it’s crazy. It’s one of my top 5 pet peeves.

But anyway, an “angle axis” is representation of an orientation. A quaternion is a representation of an orientation. So on some level they are interchangeable. But you cannot force your own axis on either of them. Thought experiment… what if you rotated upside down in your chair right now? Would would your angle + “UNIT_Y” be to get you that exact rotation? (Hint: it’s impossible) No matter how you would rotate around the Y axis, you will never turn upside down.

@alfinete said: Thirdly ... and lastly ... I find it counter intuitive to pass in an object to a method where the parameter object itself will be modified. I thought that was the general idea behind returning an object from a method. Is this a way to return more from a method than just one variable? I must admit that I had to read the javadoc for that method several times before I caught onto the idea that the vector passed in was being written to ... after reading Mr Maasing's explanation. I have also seen methods there that do both ... goodness knows why ... writing to the parameter object passed in and returning the same object as a method return.

It is a learning experience. Life is good.

I don’t know man… how many different ways can we say that the method calculated the value and STOREs it into the parameter:

I mean… it’s one thing to say “Ooops, my mistake” and another thing entirely to imply that the javadoc is confusing when it seems to clearly state exactly what it’s doing. You show me how it can be rewritten and I bet there will still be people who don’t really read it.

The method toAngleAxis needed to somehow return both an angle and an axis. How would you have suggested that be done? A new special AngleAxis object just for this purpose? In general, JME shies away from object/class garbage if it can be avoided. Since an AngleAxis would only have been used for Quaternion transformation then it would be a pretty wasted class.

To your original issue:
Now, if you actually just want to know if there is any rotation around a particular axis (x, y, or z) and not an arbitrary one then you actually can do that. Quaternion.toAngles will give you the (ahem) angles around x, y, z. This is effectively the Euler angle representation of the rotation. So while all three would be necessary to represent the full rotation, you are welcome to specifically use the x, y, or z values if that’s all you need. Just understand that you cannot go backwards from just one angle.

But if all you need to know is “how far am I rotated around the up vector”… then someOrientation.toAngles()[1]