Using

TScalar = Single;

means that if he decides to change to Doubles later on, he only has to change it in one spot, instead of refactoring the change everywhere throughout his code.

savage, do you think that using a class is the best idea for a vector? Each vector that you create will have a four byte overhead inherited from TObject (TObject.InstanceSize = 4). This overhead is because some methods of TObject are declared virtual and therefore every instance of TObject has a pointer to the virtual method table (VMT). Therefore each instance of your TVector class will be 16 bytes, whereas a record with the same members will be 12 bytes.

Another disadvantage of classes is that you must allocate each one individually. Unless you override the NewInstance and FreeInstance methods of TObject to grab memory from a pre-allocated memory pool. But then, think about what is happening here. If you are allocating a pool of 200 vectors, then you must call Create on each instance, which in turn calls NewInstance (a virtual method call, ie. slower), which in turn calls InitInstance, and other method calls such as InstanceSize. That is at least 200 calls to Create, 200 virtual calls to NewInstance, and 200 calls to InitInstance among others. Then when you free them you have to call Free, which calls Destroy (another virtual call), which calls CleanupInstance and FreeInstance, which calls InstanceSize again. That's a lot of overhead behind the scenes for such a simple class.

A lot of your methods create a new TVector instance and return that. Unless you are going to be very fanatical about remembering to free all those returned instances in the caller function, you are going to end up with a huge amount of lost memory.

I am writing a Vector unit as well, but I am using records and standard procedures/functions to manipulate those records.

The other advantage of using records is that you can block allocate a pool of them and initialize them all to zero with one call to FillChar.

I'm also using operator overloads in FreePascal so I can do something like

VectorC := VectorA + VectorB;

Now for some comments on the code.

[pascal]function TVector.Length : TScalar;
begin
result := sqrt( ( x * x + y * y + z * z ) );
end; [/pascal]

You should also provide a LengthSquare() method. A lot of algorithms can use the square of the vector length instead of the actual vector length. This saves performing an expensive square root operation.

[pascal]function TVector.UnitVector : TVector;
begin
x := x / Length;
y := y / Length;
z := z / Length;

result := self;
end; [/pascal]

Calculate once and store. Here, you are calling Length three times. But there is also a bug here. The first call to Length will give you the actual length. The second call will be wrong because you have already modified the x value. This will affect the second and third calls to Length.

[pascal]procedure TVector.Normalize;
var
ScaleValue, Len : Single;
begin
Len := Length;
if Len = 0.0 then
Exit;

ScaleValue := 1.0 / Len;

Scale( ScaleValue );
end; [/pascal]

This is a better implementation. The previous method (UnitVector) was trying to do this, but incorrectly. This method also shows another optimization. A multiplication is quicker than a divide, so if you are going to be dividing by the same value, invert it and multiply instead.

[pascal]function TVector.Reflection( const normal : TVector ) : TVector;
var
vec : TVector;
begin
vec := TVector.Create( self.SetLength( 1 ) ); // normalize this vector
result := vec.Subtract( normal.Scale( 2.0 * ( vec.DotProduct( normal ) ) ) ).Scale( Length );
end; [/pascal]

Here is an example of some memory leaks. vec is leaking. The operation of creating vec is a bit strange too. Basically what you are doing is getting a normalized version of the vector in a long roundabout way. The call to SetLength(1) is the same as calling Normalize(). Then you copy the normalized vector to vec. There is a bug in this function however in that you have normalized the vector before you calculate the reflection, so the call to Length() in the second line is always going to return 1.0.

Something for you to think about.