Friday, February 15, 2019

Be carefull with inline vars.

The new inline var is a great feature. You can save time and your code looks more cleaner.

But are there any problems with inline vars and the auto-type functionality?

Let's take a look at a small example.

Procedure Foo
var
  i : int32;
  x : uint32;
begin
  x := 0;
  for i:=0 to x-1 do
    Bar(i); // Bar would never be called.     
end;

Procedure Foo;
var
  i : int32;
begin
  for i:=0 to MyList.Count - 1 do
    DoSomeThing(MyList[i]); // Should work as expected
end;

Procedure Foo;
begin
  for var I := 0 to MyList.Count - 1 do
    DoSimeThing(MyList[i]); // Are you sure this is working?
end;

At this point, you are unable to decide!!! You have to take a look at the function result of Count. if the result is an uint32 this is not working, because the compiler takes an uint32 for I and the for is running "forever" ( from 0 to $FFFFFFFF ).

If your implementation of this list auto-creates elements on reading access you have a problem...

Edit:
Sorry about the late comments - I did not know I have to approve them.

Tuesday, February 12, 2019

Simple 3D Hello World in Firemonkey!

Games with FMX!

Is Firemonkey ready for game development - of course! There are many games out in the wild written with Delphi and also with FMX.

Why this blogpost? Because in the last weeks there are so many questions in forums or FB about this topic.

But where to start?

Do you want to go 2D? 


Great simple answer:

1.) Use a TRectangle with a PNG for your sprite(s).
2.) Use a Timer with 16ms for your game-loop.

Go and write - like me in 2015 - funny games like this:



Perhaps sometime in the future, I will release this game, if I find the time and change the stolen ROM-Images with new creations. ;-)

Do you want 3D? 


Then you might want to use a "3D Engine". Why an engine, because you do not want to do the hard work for all platforms by hand. Or you just use FMX as your engine.

This could look like this:

  1. Create a new FMX 3D application.
  2. Put a dummy object on the form
  3. Put a camera on the form
  4. Put a light on the form
  5. Place the camera at 0,0,-20
  6. Set the light to Point
  7. Place the light at 0,0,-20
  8. Put a Timer on the form and set it to 16ms
  9. In the onTimer event call Invalidate;
  10. In the onRender event call your 3D stuff.
The Form should look like this:


type
  THello3DWorld = class(TForm3D)
    Dummy1: TDummy;
    Camera1: TCamera;
    Timer1: TTimer;
    Light1: TLight;
    procedure Timer1Timer(Sender: TObject);
    procedure Form3DCreate(Sender: TObject);
    procedure Form3DDestroy(Sender: TObject);
    procedure Form3DRender(Sender: TObject; Context: TContext3D);
  private
    { Private-Deklarationen }
    fColorMaterial : TColorMaterial;
    fModelMatrix,
    fRotate        : TMatrix3D;
    fVertexBuffer  : TVertexBuffer;
    fIndexBuffer   : TIndexBuffer;
    Procedure DoInit;
    Procedure DoRotate;
  public
    { Public-Deklarationen }
  end;

In the FormCreate you can create, like in the example - a 3D object. I use a simple Triangle, but you can, of course, create any 3D Mesh or object. You also have to create Material. You can use your own Material (shader) or use the build-in.

This looks like this:

procedure THello3DWorld.Form3DCreate(Sender: TObject);
begin
  fColorMaterial := TColorMaterial.Create;
  fModelMatrix   := TMatrix3D.Identity;

  // 3 for a Triangle 
  fVertexBuffer := TVertexBuffer.Create([TVertexFormat.Vertex],3);
  fIndexBuffer  := TIndexBuffer.Create(3,TIndexFormat.UInt16);

  DoInit;
  Timer1.Enabled := true;
end;

In the DoInit, I setup a triangle for this little demo:

procedure THello3DWorld.DoInit;
var
  lVector : TVector3D;
  lMatrix : TMatrix3D;
begin
  // Create a Rotation Matrix for a equilateral triangle
  lMatrix := TMatrix3D.CreateRotationZ(120*Pi/180);
  LVector := TVector3D.Create(3,0,0); // Size 3

  fVertexBuffer.Vertices[0] := LVector;

  LVector := LVector * LMatrix; // Rotate to next point

  fVertexBuffer.Vertices[1] := LVector;

  LVector := LVector * LMatrix; // Rotate to next point

  fVertexBuffer.Vertices[2] := LVector;

  // Draw Clockwise
  fIndexBuffer.Indices[0]   := 0;
  fIndexBuffer.Indices[1]   := 1;
  fIndexBuffer.Indices[2]   := 2;

  // Create Rotation Matrix for later use 
  fRotate := TMatrix3D.CreateRotationZ(3*Pi/180);
end;

In the on Form3DRender event you can provide all your generated objects to the renderer.

procedure THello3DWorld.Form3DRender(Sender: TObject; Context: TContext3D);
begin
  if ( Context = nil ) or not( Context.BeginScene ) then
    exit;

  try
    Context.SetContextState( TContextState.cs3DScene );
    Context.Clear( TAlphaColorRec.Black ); // or any Color

    // Set ModelMatrix
    Context.SetMatrix( fModelmatrix );

    fColorMaterial.Color := TAlphaColorRec.Yellow;

    // Render Model
    Context.DrawTriangles( fVertexBuffer, fIndexBuffer,
                                          fColorMaterial, 1 );
  finally
    Context.EndScene;
  end;
end;

That's it. Now your FMX program could render any 3D object to the scene.

For entertainment, the object should rotate or do whatever you like. That's why this demo has a DoRotate method.

procedure THello3DWorld.DoRotate;
begin
  fModelMatrix := fModelMatrix * fRotate;
end;

This is a simple Matrix3D rotation. To use this rotation just call DoRotate before you call the invalidate. Normally you would measure the time difference between two frames and do the calculation for this deltaT to get even rotation speeds on all platform / CPUs. But with our timer we are fine for this demo.




With a collection of elements and some logic you can build your own 3D Engine and create some nice 3D stuff or games.





If you like to see more 3D Stuff write me a message.



Saturday, February 9, 2019

The lovely Microsoft hotline...

A very good hotline is the most important part of a software company (if you really on customer satisfaction).

I update my Mainboard, CPU, RAM. Everything was ok...

After that I copied my VM from a single M.2 to a Raid-Stripe-Set of M.2's.

A suddenly: Office wants activation a Windows, too

First, try on the Microsoft Hotline. A very grumpy man: Your Windows Key is not Valid ( I've used this key since upgraded from Windows 8 ). You have to buy a new Key.  Have a nice day. Tuuuuuut. He just hangs up.

Second try: A not so grumpy man - more helpfully - No problem Sir, please gibe my the 8 Digits from these 8 groups. Two tries. and then the same answer: You have to buy a new Key. Have a good day. By By.

And now - Windows wants a new key and office, too

Amazon: New Windows Key for 1,48€ -  yes under 2€ - the hotline cost was higher!
Windows working.

eBay: New Office Key for 7,25€ - upgraded my office from 2016 to 2019... Nice, now everything is working.