Vecmath usability improvements

Im changing vecmath for my personal needs to make it more usable. The naming of methods is a bit counter intuitive so i have changed it but the idea is the same. I think these changes can be added to the official vecmath api if necessary as they only relate to usability changes.

Constructors:

Empty constructor:

Tuple<><>()

where Type is one of: b, s, i, l, c, f, d. Yes im having one for every primitive type for concistency.

Length i >= 1 and <= 4. I have a 1 length tuple because a tuple is mutable and a Tuple1i works much like an Integer class except that Integer is immutable and Tuple1i is not. Don’t know if this is useful or not.

Tuple components are public and accesed by the names x, y, z, w.

To copy data into a tuple the literal() method is used: new Tuple3f().literal(1.0f, 1.0f, 1.0f)

There are literal methods to feed each tuple with data that take as arguments (L is length and T is type of the tuple):

1 value of type T that will be copied to all tuple components
L values of type T one for each component
1 array of type T and an offset in that array from which L values will be copied
1 tuple of length L
1 tuple of length less than L and one pad value

Methods to copy tuple components into an array like arraycopy:

T[] toArray(T[] dest, int ofs)
T[] toArray(int ofs, int len, T[] dest, int ofs2)

Methods to treat a tuple like an array. Don’t know if this is useful or not but i want the permute method so i need these for that method:

double element(int i)
TupleLT assign(int i, T value)
int length();
Class type();
TupleLT permute(int i, int j)

The usal tuple math but modified so that a tuple reference to self is allways returned. This allows for expressions like:
t.scale(s).absolute().negate()

There are operations for: absolute(), negate(), scale(s), add(t), subtract(t), clone(), toString(), equals(t), equals(t,epsilon), hashCode()

Im considering extending tuples to implement Matrices. In this case there would be an adicional TupleT9 (3x3) and TupleT16 (4x4) for matrices which would support the basic math operations for tuples. Components would be refered to c0…c8 and c0…c15. When extended by a MatrixTL the related matrix operations are added.

Another interesting functionality i am considering adding is an apply method that would work with a class FunctionLT where L is the number of arguments and T is the type of the arguments and return value, for example Function0f, Function2d, etc.

An apply or similar function could be very useful.

Filtering a tuple. Every component c is replaced by f©:

TupleLT apply(Function1T f)

Combine two tuples, c0 = f(c0,t.c0),etc:

TupleLT combine(Function2T f, TupleLT t2)

Apply a 2 arg repeatidly and return f(c0, f(c1,…)) or left associative:

T rightAssociative(Function2T fun)
T leftAssociative(Function2T fun)

For example a linear combination:

t.combine(new MultiplyFunction2f(), t2).leftAssociative(new SumFunction2f())

Another altirnative put these methods in a utility class as static for extra speed. EMath stands for extra math:

T EMath.linearCombination(TupleLT t1, Tuple LT t2)
TupleLT EMath.linarInterpolation(TupleLT t1, Tuple LT t2, T alpha)
T EMath.clamp(TupleLT t, int min, max)

I haven’t given a good consideration on this yet but i was thinking of creating classe for TupleBufferLT that would implement NIO buffers of tuples.

PS: Notice this is mostly a usability rearrangement in hope that it become less confusing to recall and select what methods to use when working with vecmath. The point is not making clever algorithms but making vecmath method easier to remenber.

It seems very interesting. However just one question : how do you see your modifications to fit into the existing maths libs ? I had a pretty violent discussions with some jME guys about that (see http://www.java-gaming.org/forums/index.php?topic=14001.new) and I wonder how you will distribute your work…

As a contribution to the official vecmath ? Backward compatibility issues
As a separate lib ? Fragmentation, and still more problems of compatibilities between non-math libs.

If you really want to upgrade vecmath i supose you can just add any new method like the literal methods. I don’t think that changing the return type for some methods from void to TupleXX wont break the code either. I supose that if you create a new vecmath jar with the new methods and then replace your old vecmath in your games if the game magicaly works then it’s only a mater of marking the methods you don’t wan’t to use anymore as deprecated. People will still be able to use it as if it was the old vecmath.

In relation to the thread you linked is this JOODE and CAL3DJ thing pure Java or just another binding? My take on this is that if we want a physics and animation api that has good qualities to be used by everyone this must be build from the ground up with that purpose in mind and it must be integrated with a vecmath api that is also done with that purpose in mind. If someone wants to program with idea of doing just what it’s good for him then it’s his choice he wants to isolate himself. This is not my thing and im not going to concern myself with it. However i have an intent of building my game engine and all it’s modules for everyone else to use and not just for my own needs or the needs of my own engine. It is a good design pratice to make an engine modules as lose coupled and complete as possible as well as all damn quality criterias for software i can think of. ;D

What is your opinion about the TupleBufferLT thing? What methods do you sugest this class should have?

“I wonder how you will distribute your work…”

It will be distributed under the GNU GPL license. I will post a link to a zip file here when it is ready or request for a java project and put it in there for everyone to download it. The package is called zeon.common.math and it will be part of the opensource game engine im building called zeon.

These are pure java : JOODE = pure java port of ODE, Cal3dj = pure java port of Cal3D (based on Dave Lloyd’s work)…

I agree completely. However what I worry about (maybe I shouldn’t) is the increasing number of math libs :

  • jME math libs
  • original vecmath
  • open vecmath implementation
  • your improved vecmath
  • zero’s math library
  • openmali (although I decided not to include any vector maths in it, as irrisor and sunsett suggested) so that’s not a problem…

Shouldn’t it have the same methods as TupleLT ? And maybe some getBuffer() additional ones.

OK. So you have already a CVS repo for zeon ? Can you give me more precisions : do you implement yourself a scenegraph, do you use a modified Xith3d, or the original I’m always interested in seeing what’s going on about game engines.

[quote="<MagicSpark.org [ BlueSky ]>,post:4,topic:27620"]
I agree completely. However what I worry about (maybe I shouldn’t) is the increasing number of math libs :

  • jME math libs
  • original vecmath
  • open vecmath implementation
  • your improved vecmath
  • zero’s math library
  • openmali (although I decided not to include any vector maths in it, as irrisor and sunsett suggested) so that’s not a problem…
    [/quote]
    I would exclude jME of the viable possibilities for a vecmath api that can be used by anyone. I don’t think this is the kind of vecmath api that was created with that in mind. It does the job that serves it’s author and does it well, thats it. Don’t know about zero’s math library. The others would be very similar to the original java vecmath so close together.

I have been thinking about this and im considering several possibilities to make a game engine more loosely-coupled in critical points. I think all engines that are being created are very good quality in terms in algorithms and eficiency. But design, usability, documentation and productivity is very lacking and that’s where i want to focus my efforts.

Starting with the scenegraph loading process we could have a unified scenegraph just for loading scenes and the data they use. Think about what was done with compilers many years ago. Compilers started to compile to pseudo machine code instead of compiling to the target machine directly.

About this scenegraph structure, primitive data would be represented either as buffers, strings or tuple properties. This can represent every possible data be it sounds, images, vertice lists, etc. Nodes itselfs and the scenegraph could be represented as a generic graph structure that can tag edges and nodes with properties which are generic dictionary data-structures. If there was a generic graph adt available in java.util i would be using it but since there isn’t one, im considering using this instead: http://www.jdsl.org/

Whats the point of this? This would make loaders independent of any specific engine. A loader implies two independent stages. One is to parse a file format and the other is to load it to memory and convert it to a temporary scenegraph or simply convert it direct to a specific engine scenegraph (this is not allways possible or aceptable). By having a common scengraph for sg loaders it’s easier to build sg loaders once that can be easly adapted to any engine later. It’s a LOT easier to translate a memory structure to a specific engine scenegraph than to change some sg loader source code, probably done by someone else, very badly documented and adapt it to a different engine scenegraph. It’s also easier this way to have operations with scenegraphs like merge scenegraphs together loaded from different formats.

Here’s some code:


ObjLoader loader = new ObjLoader();
SceneGraph sg1 = loader.load("somemesh.obj", "somemat.mtl");
VrmlLoader loader = new VrmlLoader();
SceneGraph sg2 = loader.load("something.vrml.zip"); // also loads images and sounds
sg1.merge(sg2);

Another critical point where the engine design can be more loosely-coupled is between the scenegraph and the renderer. This is probably a naive aproach but i bet the render doesn’t need to know how to work with a specific scenegraph to do his job. The renderer would work with one or more 'SceneGraphNodeIterator’s and not with a scene graph directly. This would make the renderer independent of whatever scenegraph is used. An alternative to a SceneGraphNodeIterator would be a SceneGraphListener similar to SAX for xml.

Another code example:


SceneGraph sg = loadMyScene();
SceneGraphListener listener = new SceneGraphListener(sg);
Renderer renderer = new Renderer();
renderer.buildLists(listener); // build and optimize one or more lists of cg primitives used to render the scene
RenderListsBuilder b = renderer.getRenderListsBuilder();  // in case we want to work on the lists ourselves
renderer.drawOneFrame();

One more critical point for improvement is to have the engine be optionaly controlled by: active rendering, callbacks, using a scheduller class, together with some method to organize code into a task tree similar to what was done with the DustyEngine. Notice that a task only links to the code that will be executed by the task. It represents an interval of time and possibly some constrains (precedence constrains, etc) for task to calculate task activation.

These are the main objectives for my engine. Mostly make an engine that is more loosly-couple in key places, improve usability and productivity and add a task manager.