PDA

View Full Version : Matrix unit



dmantione
15-10-2006, 08:26 PM
Two years ago I did add a 2d,3d,4d matrix unit to FPC, and one of my targets was game developers. I studied some games written in FPC and they use their own matrix unit.

So my questions are:
* Are you aware that FPC has a matrix unit?
* Do you think it suits the needs of games?
* If you implemented one yourself, why did you do so?

tpascal
15-10-2006, 10:54 PM
Hi,

I am not a FPC user so i would say no to your first question, if you matrix unit handle most needed matrix operations then yes it should suit for game development.

* If you implemented one yourself, why did you do so?

I found interesting this question, why some one would implement somthing from scracht if somthing already exist?...

I did most my own vector, matrix units first, i think those are stuf that you learn how to do it at the same time you learn for what they are good for; i mean i did not know that i needed to google for an unit that does dot and cross product in vectors until the day i read an article about vector math which teach why those calcs are needed and it also include how to do those calcs; so i think part of the procces of learning those stuf including actually coding those stuff too; i am sure that is why everytime i saw a source coded project released i found they most the time use his own vector and matrix units.

By the way, there is a well know unit called geometry.pas which include matrix and vector procedures but coded in assembler, so most people (like me) could think that should be run lot faster!, so maybe it could be a good idea to copy/paste those version, :roll:

Another reason why i should preffer to code somthing my self is becouse somtimes programmers ARE SO LAZZY for document properly the units they release to the public; they like to give program examples instead; they say "please learn how to use my unit from this ready to run example" instead of of documenting exactly what the procedures are for and what the parameters mean. I preffer to expend two months coding for somthing my self but i will know fully how it works than expend 15 days figuring out more or less how works someone else code but not knowing fully if i am using it properly.

tp

cragwolf
16-10-2006, 01:04 AM
No, I didn't know! I can't believe I never noticed it before. I will have to try it out.

cragwolf
16-10-2006, 05:15 AM
So if I declare a matrix like so...

var mat: Tmatrix2_single;

...then I would access elements like so...

x := mat.data[1, 1];

Is that right? It would be nice if you could do mat[1, 1], but I understand why you decided to go with objects. Also, being able to typecast with similar types is a nifty feature. And I like the cross product operator:

A := B >< C

dmantione
16-10-2006, 06:43 AM
So if I declare a matrix like so...

var mat: Tmatrix2_single;

...then I would access elements like so...

x := mat.data[1, 1];

Is that right? It would be nice if you could do mat[1, 1], but I understand why you decided to go with objects.

Yes, this is correct. I tried to make the elements directly accessible with a default property, but it is not possible to define a default property this way.

dmantione
16-10-2006, 06:50 AM
Hi,
By the way, there is a well know unit called geometry.pas which include matrix and vector procedures but coded in assembler, so most people (like me) could think that should be run lot faster!, so maybe it could be a good idea to copy/paste those version, :roll:


This is exactly the point of having a matrix unit shipped with the compiler, if people write their own matrix unit, usually they don't have the time and resources to implement everything in assembler. By working together the effort needed to implement everything in assembler is well spent.



Another reason why i should preffer to code somthing my self is becouse somtimes programmers ARE SO LAZZY for document properly the units they release to the public; they like to give program examples instead; they say "please learn how to use my unit from this ready to run example" instead of of documenting exactly what the procedures are for and what the parameters mean. I preffer to expend two months coding for somthing my self but i will know fully how it works than expend 15 days figuring out more or less how works someone else code but not knowing fully if i am using it properly.


I agree 100%. The documentation for the matrix unit is currently 280kb of source which translatetes to 2,6 MB of HTML. However, I still haven't finished. It is a monk work, because every routine needs to be documented 9 times; three matrix dimensions times three precisions. :(

Clootie
16-10-2006, 09:24 PM
So my questions are:
* Are you aware that FPC has a matrix unit?
* I was not aware of it.


* Do you think it suits the needs of games?
* If you implemented one yourself, why did you do so?
Partly I understand the question as: "Why no games use it?"
Let's see what came to mine mind after some looking at unit:
* It's not cross-compiler, i.e. it's not possible to use it in Delphi
* matrix-matrix multiply implemented using cycles
* no SSE handtuned version of functions
* most of graphic libraries already cames with they own "native" vector types, so why one need to struggle with type conversion between them FPC matrix types.

Diaboli
16-10-2006, 09:51 PM
wouldnt a single matrix [x,y] be the same as a 2-dimensional array in delphi?

var
Player: Array of Array of TPlayer;

Player[x,y].Name := 'NewPlayer';


can make more dimensians also, if you make a type that is either a single array or a two-dimensional...


type
TPlayerArray = Array of TPlayer;

var
Players: Array of Array of TPlayerArray;

Player[x,y,z].Name := 'NewPlayer';

dmantione
16-10-2006, 10:58 PM
wouldnt a single matrix [x,y] be the same as a 2-dimensional array in delphi?


Absolutely not. A vectors and matrices are all about geometry. If you have a 3D game, you need them. For example you rotate an object by multiplying all its points with a rotation matrix. A matrix unit takes care of this multiplication, for example.

dmantione
16-10-2006, 11:10 PM
So my questions are:
* Are you aware that FPC has a matrix unit?
* I was not aware of it.


* Do you think it suits the needs of games?
* If you implemented one yourself, why did you do so?
Partly I understand the question as: "Why no games use it?"
Let's see what came to mine mind after some looking at unit:
* It's not cross-compiler, i.e. it's not possible to use it in Delphi
* matrix-matrix multiply implemented using cycles
* no SSE handtuned version of functions
* most of graphic libraries already cames with they own "native" vector types, so why one need to struggle with type conversion between them FPC matrix types.

Thanks for the feedback. Delphi compatibility is a bit hard with the operator overload stuff, which is IMHO what it makes elegant. It could be made GNU-Pascal compatible, since that compiler uses the same syntax as FPC. Unfortunately nobody uses GPC. I agree that to make it really attractive it needs optimized routines, which includes unrolled multiplies and SSE. The binary format is intentionally just a two-dimensional array, which hopefully maximizes the chance that you can use it in a library without difficult conversion.

michalis
17-10-2006, 02:21 AM
When I started my own vertor/matrix unit (you can see it in http://www.camelot.homedns.org/~michalis/kambi_vrml_game_engine.php,
unit VectorMath in subdir base/) I wasn't aware that there is a matrix unit in FPC. Actually, I'm not sure whether it existed then, as it was around 2002.

Then, when I first saw Matrix unit, I saw that it uses old-style TP objects... so I suspected that maybe it's some old code, not maintained. Moreover, it didn't have anything to offer me, aside from nice operator overloads that I could add to my unit at any time. My unit already had way more operations.

To enumarate everything that I expect from the vector/matrix unit, I would have to paste here the interface of my whole VectorMath unit :) BTW, you have complete permission to reuse any parts of my VectorMath unit for FPC Matrix unit, under FPC RTL license.

The most important information for me is that now I know that Matrix unit is supposed to stay and be maintained and improved. I'll see whether I can migrate to it --- at least reusing it's Tvector*_data and Tmatrix*_data types should be an easy and quick start.

cragwolf
17-10-2006, 06:03 AM
Here is what michalis expects:

http://www.camelot.homedns.org/~michalis/src/pascal/docs/html/VectorMath.html

:)

grudzio
17-10-2006, 05:07 PM
* Are you aware that FPC has a matrix unit?


Now I am :)


* Do you think it suits the needs of games?
Another problem I see is the compatibility with 3D apis, OpenGL in my case . Is the column/row ordering same as in OpenGL. Is there an easy way of sending and retrievng matrices to and from OpenGL and so on. Although a good, optimised 3D math library shipped with a compiler is a nice thing to have.

* If you implemented one yourself, why did you do so?
Generaly I prefer to write my own code then made by others. I know that often it is reinventing the wheel, but it is a learning experience and it is easier to fit my own code into my projects.

dmantione
17-10-2006, 06:31 PM
* Do you think it suits the needs of games?
Another problem I see is the compatibility with 3D apis, OpenGL in my case . Is the column/row ordering same as in OpenGL. Is there an easy way of sending and retrievng matrices to and from OpenGL and so on. Although a good, optimised 3D math library shipped with a compiler is a nice thing to have.

No, the row/column ordering doesn't match OpenGL. Interfacing with OpenGL is still very easy, i.e.:

var m:Tmatrix4_single;

begin
with m.transpose do
glLoadMatrixF(@data);

I'm going to put this into the documentation.



* If you implemented one yourself, why did you do so?
Generaly I prefer to write my own code then made by others. I know that often it is reinventing the wheel, but it is a learning experience and it is easier to fit my own code into my projects.

Yes, that makes sense.

dmantione
17-10-2006, 06:35 PM
To enumarate everything that I expect from the vector/matrix unit, I would have to paste here the interface of my whole VectorMath unit :) BTW, you have complete permission to reuse any parts of my VectorMath unit for FPC Matrix unit, under FPC RTL license.

Thanks! I've already been thinking about adding more geometry code, however, I decided to watch what the response to the matrix unit was, the FPC to do list is long as ever :D

Clootie
18-10-2006, 09:15 PM
No, the row/column ordering doesn't match OpenGL. Interfacing with OpenGL is still very easy, ....
Wait, for a long time I was convinced by someone that both D3D & OpenGL matrices are equal if we look at _binary_ format in memory. It's just API's what tread them differently. I.e. in books matrices and vectors are printed differently (I mean row/column "visualization").

michalis
21-10-2006, 02:19 PM
No, the row/column ordering doesn't match OpenGL. Interfacing with OpenGL is still very easy, i.e.:

var m:Tmatrix4_single;

begin
with m.transpose do
glLoadMatrixF(@data);

I'm going to put this into the documentation.


Or just
glLoadMatrixF(@m.transpose.data);

Actually, it would be nice to add a unit like GLMatrix that defines overloaded versions of glLoadMatrix routines that just take Tmatrix4_single/double as arguments and do the transpose inside implementation.

I even thought about doing descendants like TMatrix4_single_GL that have methods like glLoadMatrix with implementation like


procedure TMatrix4_single_GL.glLoadMatrix;
begin
GL.glLoadMatrix(@transpose.data);
end;


... but this will not be so nice, since you will have to override some operators again for new TMatrix4_single_GL class, and if you receive your matrix instance from some non-OpenGL-related unit then it will still have normal TMatrix4_single class, not TMatrix4_single_GL. So making non-object procedures like glLoadMatrix(M: TMatrix4_single) would be more general solution to "hide" the "transpose." call from the eyes of the programmer.

michalis
21-10-2006, 02:29 PM
I forgot to add that two days ago I added a program to pasdoc that works like a Pascal preprocessor, see http://pasdoc.sipsolutions.net/OtherTools. It can resolve many things, like $define, $ifdef, $include and FPC macros. The idea was to allow you to use FPC macros when developing your units, and then port them to Delphi easily by automatic convertion through this program.

Oh, and it works !

Unfortunately, it doesn't evaluale expressions inside $if constructs, and Matrix unit uses $if a lot. So to port Matrix unit to Delphi one would have to convert them to simple $ifdef with appropriate symbols. And of course the operator stuff would have to be put only inside {$ifdef FPC} --- and I agree here with Daniel that the overloaded operators stuff is one important advantage of this unit in FPC.

Anyway, if someone is really pressed into converting Matrix unit into Delphi, then you have now at least a way to automatically resolve all FPC macros for Delphi.

dmantione
21-10-2006, 03:10 PM
Actually, it would be nice to add a unit like GLMatrix that defines overloaded versions of glLoadMatrix routines that just take Tmatrix4_single/double as arguments and do the transpose inside implementation.


I like this idea. It'll make OpenGL programming a bit more high level. We could also add overloads that accept open arrays of vectors, abstracting the pointer stuff that is necessary for the *v functions.



I even thought about doing descendants like TMatrix4_single_GL that have methods like glLoadMatrix with implementation like


procedure TMatrix4_single_GL.glLoadMatrix;
begin
GL.glLoadMatrix(@transpose.data);
end;


... but this will not be so nice, since you will have to override some operators again for new TMatrix4_single_GL class, and if you receive your matrix instance from some non-OpenGL-related unit then it will still have normal TMatrix4_single class, not TMatrix4_single_GL.

Well, the multiply operator could call a virtual method to do i.e. multiplication, then it should be possible to do it with only one set of operators defined. However, I don't know wether this is desired for speed reasons.

dmantione
21-10-2006, 03:15 PM
I forgot to add that two days ago I added a program to pasdoc that works like a Pascal preprocessor, see http://pasdoc.sipsolutions.net/OtherTools. It can resolve many things, like $define, $ifdef, $include and FPC macros. The idea was to allow you to use FPC macros when developing your units, and then port them to Delphi easily by automatic convertion through this program.

Oh, and it works !


Nice :)



Unfortunately, it doesn't evaluale expressions inside $if constructs, and Matrix unit uses $if a lot. So to port Matrix unit to Delphi one would have to convert them to simple $ifdef with appropriate symbols. And of course the operator stuff would have to be put only inside {$ifdef FPC} --- and I agree here with Daniel that the overloaded operators stuff is one important advantage of this unit in FPC.


Do you think there is a way to do the same with the new Delphi overloaded operators? If yes we could consider to write a Delphi unit that results in the same syntax for users of the library.

michalis
21-10-2006, 03:50 PM
Do you think there is a way to do the same with the new Delphi overloaded operators? If yes we could consider to write a Delphi unit that results in the same syntax for users of the library.

I don't know, didn't use Delphi to do anything serious since a long time... Any links to Delphi operator overloading syntax ?

technomage
21-10-2006, 03:57 PM
Operator overloading is done using what I would call Operator Mapping. The following example the compiler "maps" + operator to the Add Method.


TMyClass = class
class operator Add(a, b: TMyClass): TMyClass;
end;



var a,b : TMyClass;
begin
a + b; // Calls TMyClass.Add(a, b: TMyClass): TMyClass
end;


This is straight out of the BDS 2006 Manual. I think this is different to the way free pascal does it.... :?:

michalis
21-10-2006, 04:07 PM
This is straight out of the BDS 2006 Manual. I think this is different to the way free pascal does it.... :?:

Yeah, definitely different... So in Delphi operator overloading may be done only for classes ? No way do to it for old-style objects ?

dmantione
21-10-2006, 04:15 PM
Well, the main reason to do objects is that they don't need to reside on the heap, which means temp matrices are in the fast stack. Using classes results in memory management issues, i.e.

a:=b*c+d;

.. results, depending on compiler smartness, in one or two intermediate matrices. How does BDS solve this in native mode?

technomage
21-10-2006, 04:30 PM
Yeah, definitely different... So in Delphi operator overloading may be done only for classes ? No way do to it for old-style objects ?

Borland Have depreciated the myclass = object , this has been the case since delphi 3 (I think) , it's something they supported for old applications.

JSoftware
22-10-2006, 12:26 AM
just use it with records in delphi. BDS supports functions inside records and even supports operator overloading for records

marcov
29-10-2006, 09:22 AM
just use it with records in delphi. BDS supports functions inside records and even supports operator overloading for records

That's a useless .NET copycat feature; They had it for .NET, and enabled it for D2006 at the same cost (afaik BDS2005 doesn't support it?), but without any merit.

The old object model (1990 or thereabouts) already was like that + that it supported virtual methods.

Almindor
11-11-2006, 08:11 PM
Using objects here is perfectly sane since objects are very fast compared to classes, and you might want to have a memory-free experience with matrices.

Strictly speaking, apart from properties (afaik) and metaclasses, there's very little classes offer which is worth the extra performance loss and inability to use them on stack.

dmantione
12-11-2006, 03:59 PM
It took a while, but nowadays one can use properties in objects. (Since 2.0.0 as far as I know.)