Proposal: moving math stuff to an independent repository

socram8888

Member
Contributor
As Cervator suggested, I'm opening this thread to discuss whether it's or not a good idea to move the math stuff (org.terasology.math) and random classes (org.terasology.utilities.procedural and org.terasology.utilities.noise) to an independent repository, which would be downloaded as a dependency, much like the TeraBullet repository.

There is an old thread talking about something simmilar: http://forum.movingblocks.net/threads/teramath.205/, but apparently was abandoned.
 

msteiger

Active Member
Contributor
World
Architecture
Logistics
I wonder what happened to the code! It sounds as if at least some classed existed somewhere. I'm asking because I really don't like working with vecmath (public mutable members, many missing methods, etc) ..
It would be great to have at least some basic geometric interfaces such as Point, Vector, Rectangle and so on..
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
I wonder what happened to the code! It sounds as if at least some classed existed somewhere. I'm asking because I really don't like working with vecmath (public mutable members, many missing methods, etc) ..
It would be great to have at least some basic geometric interfaces such as Point, Vector, Rectangle and so on..
I partially agree with you. Vecmath is... not how I would design a math library. The public mutable members are not wonderful but I can see why it was done: v.x += 3; is syntactically better than anything you can do with methods. I'm happy with the classes being mutable (this is a performance choice around allowing object creation to be avoided), but would probably have a ConstVectorXX base interface which is immutable to allow methods to "guarantee" they don't modify the vectors (e.g. public void moveTo(ConstVector3f v) would guarantee v isn't changed - much like C++'s const arguments). I don't mind the classes missing methods - these can be added in static helper libraries - but it would be nice if more of them were included in the library. Applying transforms through Matrices/Quaternions to Vectors in particular is very much missing. And some of the initial values are off (an empty constructor created Quaternion or Matrix are not identity Quaternions/Matrices). I would also avoid Cloneable completely, but its presence doesn't hurt.

On the other hand it is the closest to a standard vector math library that Java has which is suitable for games (Apache Commons Math has some vector support, but it is very sparse - only doubles, only 3D). And I'm not sure we're in position to drive the creation of a new standard library. Perhaps we should anyway? Spout do have a math library as well, but we can't use it due to their license choice, and it is all immutable types which I'm not convinced is appropriate.
 

Mike Kienenberger

Active Member
Contributor
Architecture
GUI
If you want to get involved with Apache Commons Math, it should be pretty trivial to do.

Disclaimer: I'm an ASF member.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
I've got a chronic case of frameworkitis / library-itis so I'm trying to stay low profile :D

But Apache? Sounds cool, if Mike Kienenberger is already involved and able to help guide. If there is potential to flesh that out more, anyway. In that case would noise fit into the same lib? Although with that separate noise lib I mentioned on GitHub maybe we could have both - although yet again that one has its own math so .. yay ;)

Or we could just cram everything into our own. I'm happy either way!
 

Mike Kienenberger

Active Member
Contributor
Architecture
GUI
While I'm not directly involved with the commons math project, I am more than happy to help anyone who desires get actively involved with the Apache Commons Math project with any guidance they may need. You shouldn't find getting involved there much different than getting involved here. The main difference would be that everything is done by mailing lists so that there's a clear consistent record of all project communications (although some ends up in the issue tracker at times). Some projects use git, but most still use svn. Not sure what commons Math uses off-hand. There's always git-svn.

But I'm not pushing any particular math frameworks since I don't have experience working with any of them. I know that becoming a member of an Apache project has a low entry bar -- mainly that you want to contribute and you're willing to discuss your changes with other project members -- since growing a project's community is considered an important component of any project at the ASF.
 

msteiger

Active Member
Contributor
World
Architecture
Logistics
In my humble opinion, commons.math doesn't contain that kind of math we need :-/

I'm using java.awt and vecmath which I find painful to use, but they work very well and bug-free.
I've looked into JTS (stalled since 2006) and javaGeom (not sure, but I think it's dead). The former focuses on geo-related contents (GIS, etc), the latter come quite close to what I was looking for. Unfortunately it seems to be a one-man show and the guy lost interest (no offense, but that makes it less attractive to use).

This question here served as a basis for me:
http://stackoverflow.com/questions/2115976/geometry-library-for-java

My conclusion is that there is no proper java geometry library, especially not for integer math.

* I'm also not a big fan of static helper classes: people don't know about them, so they don't look at them.
* I'm not an expert on JVM GC, but I have the impression that object that live only with one method are basically free of charge. Being young-generation (even eden) object, they live on the stack. Especially sinve Java6 (u21 I believe) using many short-lived objects could/should be quite cheap. See this for details:

http://stackoverflow.com/questions/13660871/jvm-garbage-collection-in-young-generation

Final words: Maybe we can slowly replace vecmath by adding our own methods and classes just as guys have been doing over the past years. One example: a ConstPoint2i that throws UnsuppOpException just Collections.unmodifiable*() does.
 

Mike Kienenberger

Active Member
Contributor
Architecture
GUI
Unfortunately, JTS is "GNU Library or Lesser General Public License version 2.0 (LGPLv2)", which wouldn't be compatible. Otherwise, I'd say just fork the code and develop it ourselves as a starting point if it wasn't being maintained sufficiently.

Vecmath is probably the same issue with the standard oracle license patent issues, short of writing a bunch of wrapper classes around it, which is probably not what you'd want for a high-performance math library :)
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
xkcd.com/927/

It is annoying that pretty much every gl framework also introduces its own vector types, which are embedded in their jar. Both Libgdx and Lwjgl, for instance. They're also typically somewhat sporadic in their feature set, since they're designed to solve specific issues for those frameworks.

In my humble opinion, commons.math doesn't contain that kind of math we need :-/
Definitely agree.

* I'm also not a big fan of static helper classes: people don't know about them, so they don't look at them.
The reason I think they are somewhat inevitable with a math library is otherwise you end up filling your math types with hundreds of methods, many of which are are somewhat business domain specific. This means you end up with a lot of methods to maintain in those classes. Splitting them out reduces the maintenance burden on that class. Note that none of those methods need private access to the Vector object.

Exactly where you draw the line is the question. I feel rotating a vector by a quaternion certainly should be in there (probably in the quaternion). Would you put lerp into a Vector? Slerp into quaternion (all three varieties)? Min/Max methods? Ultimately I like to think of a vector to be a math primitive like a float, so maybe not?

Unfortunately it seems to be a one-man show and the guy lost interest (no offense, but that makes it less attractive to use).
I very much agree. This is why, if we were to go ahead and make an independent math library, I would be inclined to make sure we can provide it sufficient support.

Final words: Maybe we can slowly replace vecmath by adding our own methods and classes just as guys have been doing over the past years. One example: a ConstPoint2i that throws UnsuppOpException just Collections.unmodifiable*() does.
In addition to license issues, this doesn't allow fixing the fundamental issues with vecmath, like methods that don't allow chaining, bad constructors, and the exposure of fields.

I have some concerns over the idea of a ConstPoint2i class as you describe. The reason I suggested an interface that is extended by the non-const Vector implementation (I don't like the Point name btw, but that is mostly a personal preference thing) is it allows a method to indicate whether or not it modifies the vector, so the caller knows whether it may want to do a defensive copy. A full Vector2i would implement the ConstVector2i interface (which suggests the name is probably bad, is there a good name suggestion it is the interface for the non-modifiable parts of a Vector?), so a Vector2i could be passed to a method requiring a ConstVector2i. An actual unmodifiable subclass means you would have to create a copy, and even if the jvm/GC handles short lived classes efficiently you would still be adding extra object creation over not doing that. You might as well just copy the Vector2i as another Vector2i and skip the ConstVector2i entirely, if ConstVector2i is a separate class or inherits Vector2i.

Having all vectors immutable is also sort of tempting but the resulting syntax for manipulation, particularly for individual dimensions, suffers as a result. For most of the other math classes I created - Rect2i, Region3i, and Color - I did go with immutability because that sort of individual dimension manipulation wasn't an issue, and manipulation in general wasn't as common.
 

msteiger

Active Member
Contributor
World
Architecture
Logistics
I'm trying to put the idea into code, starting with a const interface that might look like this:
Code:
interface Vector2ci {
  public int getX();
  public int getX();
}
extended by a non-const implementation like this:
Code:
class Vector2i {
  public void setX(int nx);
  public void setY(int ny);
}
Now, if I give you a Vector2ci (the const interface), how could you know that I didn't give you the modifiable sub-class? You can't modify it - you would even believe that it's impossible (because it's const), but I can change it anyway.

I would assume that this problem is also the reason why the JDK guys use mutable base classes and derive unmodifiable views from them that throw UnsupportedOperationExceptions for setters. Ugly, but safe.

In my other project I use AbstractVector2i, a base class for both the const and the mutable implementation. Maybe this could be a viable solution?
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
Ah, you've missed my intention. There would be no immutable implementation (or at least, not necessarily). The point of the const interface (bad name, perhaps ReadableVectorxx?) is not a guarantee that the vector will not change, but a way of specifying with a little rigor that the method you pass it to won't change it. It isn't supposed to be a guarantee of it being immutable. The intent would be to prevent errors where a method alters a vector it shouldn't, and as an indicator when a method will not change the original vector. The method implementation should create a copy if it wants to make any changes or retain the vector - without requiring the caller have to create the copy.

Yes, casting can get around the intent. Basically this is sacrificing safety for performance, compared to having immutable vectors, but gaining clarity compared to just having Vectorxx.

While an immutable vector may also be useful, it forces defensive copying by callers - callers would have to create an immutable copy of their vector, and then the method itself may need to create a mutable copy for what it does. Or the caller could just create a defensive Vector2i copy, since the immutable class doesn't add anything - but then there would be nothing but comments to specify whether a given method may or may not alter the vector (there is probably some use for immutable vectors outside of these cases, but this is the use case I'm interested in).

Example:

Code:
public interface ReadableVector2i {
    int x();
    int y();
}
 
// I would probably just make this a class, overly elaborate inheritance structures is another issue with VecMath
public final class Vector2i extends ReadableVector2i {
  public void x(int x);
  public void y(int y);
 
  public void set(int x, int y);
}
 
public static Vector2i add(ReadableVector2i a, ReadableVector2i b) {
    // This method cannot change a or b without cheating.
    return new Vector2i(a.x() + b.x(), a.y() + b.y());
}
 
public static void demo() {
    Vector2i a = new Vector2i(1, 2);
    Vector2i b = new Vector2i(5, 6);
    Vector2i c = add(a, b);
}
 

msteiger

Active Member
Contributor
World
Architecture
Logistics
I get it now. There's probably no perfect way to solve this. To me, the logical step would be to setup a sidekick-project and implement a few classes/methods/tests to get a feeling for it.

This would also be a nice opportunity to try out google's micro-benchmark suite Caliper (at least for me)
http://code.google.com/p/caliper/‎
 
Top