Vector refactor and basic enhancements

Hello there!

I’d like to make some small enhancements I find useful to vector classes. Here’s what I plan to do :

  1. Move the Vector3d class from the blender subproject into the core project in the same package as other vector classes.
  2. Add the missing transformVectorLocal method to the Transform class.
  3. Add the following methods to the Vector2f class : s̶e̶t̶F̶r̶o̶m̶V̶e̶c̶3̶X̶Y̶,̶ ̶s̶e̶t̶F̶r̶o̶m̶V̶e̶c̶3̶X̶Z̶,̶ ̶a̶d̶d̶L̶o̶c̶a̶l̶F̶r̶o̶m̶V̶e̶c̶3̶X̶Y̶,̶ ̶a̶d̶d̶L̶o̶c̶a̶l̶F̶r̶o̶m̶V̶e̶c̶3̶X̶Z̶, toVector3fXY, toVector3fXZ, perpendicular and perpendicularLocal.
  4. A̶d̶d̶ ̶c̶o̶p̶y̶ ̶c̶o̶n̶s̶t̶r̶u̶c̶t̶o̶r̶s̶ ̶t̶o̶ ̶a̶l̶l̶ ̶v̶e̶c̶t̶o̶r̶ ̶c̶l̶a̶s̶s̶e̶s̶.̶
  5. O̶v̶e̶r̶l̶o̶a̶d̶ ̶t̶h̶e̶ ̶V̶e̶c̶t̶o̶r̶3̶d̶.̶s̶e̶t̶(̶V̶e̶c̶t̶o̶r̶3̶d̶ ̶v̶e̶c̶t̶)̶ ̶m̶e̶t̶h̶o̶d̶ ̶s̶o̶ ̶t̶h̶a̶t̶ ̶i̶t̶ ̶c̶a̶n̶ ̶a̶l̶s̶o̶ ̶t̶a̶k̶e̶ ̶a̶ ̶V̶e̶c̶t̶o̶r̶3̶f̶.̶
  6. Add the missing Vector3d.set(int index, double value) method.
  7. Add the Vector2i and Vector3i classes which are basic vector classes with the add, subtract, mult methods and their respective local variations. One use of the integer vector classes is for map keys.
  8. Adjust the 2nd overload of the method Vector3f.interpolateLocal that takes two Vector3fs, as it is wonky. After reflection, maybe it’s best to leave it be for optimization but to add a non-local method.
  9. Add the following methods to vector classes : subtract, subtractLocal, add and addLocal methods that take only one scalar.
  10. Use SimMath as the base for the new math extension subproject.

The numbers 2 is optional but I find it useful. The number 5 is totally optional. I think the rest is good. What do you think? Also, how can I create a remote branch on jMonkey repository so that I can work on this? I mean, I think I need some sort of access. Here is my Github account. There’s almost nothing, as I am more of a Bitbucket guy.

You fork the project and then make a pull request from your (personal) repo.

2 Likes

This is an explanation on GitHub using netbeans. Adapt for your flavor of IDE.

https://wiki.jmonkeyengine.org/jme3/build_jme3_sources_with_netbeans.html#information-on-pull-pushing-commits

1 Like

That would be pretty awesome imho, bonus points if you give them an addLocal/subtractLocal/etc(Vector3f ) methods and vice versa Vec2/3i versions for the Vector2/3f classes.

Are those really necessary though? Seems like more work spelling those out than just set(a.x,a.z) or addLocal(a.x,a.z). It’s also easier to change if you need to switch out the components for some reason.

I suppose it would come handy if someone had a really really long vector name I guess?

1 Like

The naming of interpolateLocal is wonky, the 2nd version that accepts 2 Vector3s should probably be renamed interpolate and should not effect the local variable.

Could you add this in to your changes ?

1 Like

Yeah, I feel you. I knew it was kinda too specific from my game. I’ll just drop those methods.

Hmmm you are right. So, to recapitulate : rename the 2nd overload that accepts 2 Vector3fs to interpolate, make it take the same arguments as interpolateLocal and make it return a new Vector3f. Is that correct?

For backwards compatibility and consistency, perhaps deprecate the 2nd one since it’s name is misleading (not really misleading, but the functionality is inconsistent), and add the new ‘interpolate’ method that takes one Vector3f (and float changeAmt) that returns the result and does not effect the internal (local) value.

Make sense ? Thoughts anyone ?

2 Likes

I think that the second interpolateLocal is there for optimization purposes, lets say that you are aiming to generate as little garbage as possible, you might want to save the interpolated result on the same vector over and over, with your proposed change:

result.set(a.interpolate(b,i));

This will generate an unneeded object .

While the current code

result.interpolateLocal(a,b,i);

won’t generate any garbage.

This might sound as micro optimization but if you have high framerate and you run this several times on every frame, it will start to become noticeable.

But I agree that a non local interpolate method is needed.

1 Like

What would the engine need with Vector3d and Vector3i? com.jme3.math is in support of the engine.

As to the interpolate stuff… it was even more confusing before because it was just called interpolate() and actually modified the local value also. We renamed it to interpolateLocal() and broke backwards compatibility for a while just so you guys can speculate about now having an interpolate() that doesn’t do that. It may still be too soon for those people who haven’t upgraded. :slight_smile:

This is where it starts to become wonky actually because you could have two perpendicular vectors, one is CCW and one CW. Which one will the method use?

Isn’t Vector3f#clone() actually the same thing then?

Mixing and/or Adding Integer and Double Vectors is a bit meh in my opinion as well, it depends actually. The problem is that people won’t be aware that the engine doesn’t benefit from you using Vector3d’s, so it’s only useful in your own use-cases and there only when you know what you’re doing and need that precision (e.g. in a space game, setLocalTranslation() would still be flawed). Most of the time you’d rather page.

The use case as “tile index” in a map is possible, but in most cases you’d rather use your own subclass, even if it’s only a little private one. That being said the engine could still use it for things like .getScreenResolution(), but what happens when you try to subtract a Vector2f from a Vector2i? Will it work? Will it silently return a Vector2f?

The engine itself wouldn’t need it I suppose but, to me, it doesn’t make sense to put Vector3d in the blender subproject. For exemple, for my game, I had to use Vector3d and, to do so, I had to import the whole blender subproject :confused:

I think it makes more sense to gather all vector classes together.

Hmmm you are right. Maybe I could just add the new overload mentioned?

The documentation is supposed to rectify that. The perpendicular vector of a 2D vector is its cross product and takes only the vector as parameter (I learned that there are multiple forms for cross products). As I recall, it computes the CCW perpendicular vector.

No. Clone will clone everything, including all data from the child classes. A copy constructor will only copy the data from the current class and create a new object with it. Let’s say you need 1 500 000 Vector3fs and you happen to have a variable to initialize them with called Vector3f vec6 = new Vector6f(), which is an instance of the class Vector6f, which inherits from Vector3f for the purpose of this example. Then, cloning vec6 will allocate 4 500 000 floats for nothing and will still be kept in memory, even if the user call set() on them as they will be seen as Vector3f. Using the copy constructor assures the programmer that only the Vector3f data is copied.

What is Vector3d actually? I never used it. If it has to be exposed but is not useful for the engine, then it should be a subproject, like jme-extendedmath or something like this.

Vector3d is something internal to the blender plugin as the blender plugin needs to do some of its own double-based vector math, I guess. Since games should be using the blender plugin I guess it’s not relevant here.

As for an external library… there is: GitHub - Simsilica/SimMath: A double-based math package similar to JME's float-based math classes.

1 Like

Vector3f is final so there are no “child classes”… and even if there were, they would require constructors that would then copy the data (or not) as needed. No more or less efficient than clone.

I think this is a great idea. Vector3d is the same as Vector3f but with doubles.

That’s cool but I do believe Vector3i and Vector2i could be a great addition. If we were to add a subproject like @nehon said, we could use your library plus the small classes I proposed. What do you think?

Oops, my bad. I should have checked that.

What I was talking about was :

/* Copy constructor.
*
* @param source The source to copy.
*/
public Vector3d(Vector3d source) {
    this.x = source.x;
    this.y = source.y;
    this.z = source.z;
}

Anyway, the fact that the class is final removes the possible need for this.

I just found out that, in my modified version of the engine, I have subtract, subtractLocal, add and addLocal methods that take only one scalar. Do you guys think this could also be useful? Currently, those methods only either take a vector or 3 scalars.

I’ll start working on this in two weeks because I have lot going on with school that just started.

It already has Vec3i: https://github.com/Simsilica/SimMath/blob/master/src/main/java/com/simsilica/mathd/Vec3i.java

I’ve found even in JME that sometimes the Vec2 related classes are more trouble than they are worth. But I’m not opposed to adding them.

I don’t think it should be a JME subproject, though. JME doesn’t need it and it would mean release cycles are loooooooooooooooooong for something that is otherwise super-simple to iterate.

Then what do you propose? Should I just fix some mentioned hiccups instead of doing so plus adding new classes?