Skip to content

RAD Studio XE8 Launch in Brno today was great!

RAD Studio XE8 Launch event in Brno today was great!
More info at my blog at community.embarcadero.com

TBeacon and New Appmethod at IT DroidCon Today

Today was my first to demonstrate the new support beacons in the new Appmethod, Delphi XE8 and C++Builder XE8 at IT Droid Con.

More info at my community.embaracadero.com blog!

Delphi live coding in Brussels - Code Monkey is back!

Just back from Brussels from the second live workshop "Develop complete Windows, mobile, web service and cloud solution in 1 day!"

More info on my community embarcadero blog here:

http://community.embarcadero.com/index.php/blogs/entry/delphi-live-coding-in-brussels-code-monkey-is-back

Delphi Live Tutorial in the Netherlands and CodeMonkey

We had 160+ enthusiastic Delphi developers on the "Develop a complete Windows, mobile, web service and cloud solution in 1 day!" event yesterday in Hoofddoorp, The Netherlands!

Read more at my embarcadero community blog!

FireDAC Skill Sprints every Thursday start this week!

I’m very excited to host the first FireDAC Skill Sprint this week! For the next 10 weeks there will short, 20 minutes long free webinar focused on different aspects of FireDAC, the best database access library for C++ and Object Pascal applications, both VCL and Multi-device, FireMonkey!

There are three slots for different time zones. Each webinar is followed by live Q&A!

FireDAC Skill Sprints are free to attend, but you need to register at http://forms.embarcadero.com/15Q1FireDACSkillSprintsWebinarSeries

Here is the agenda for the next 10 sessions on FireDAC:

Date Topic
January 22 Introduction to FireDAC
January 29 Monitoring and Tracing
February 5
Cached Updates and Auto-inc Fields
February 12 Array DML
February 19 Cascading Options System
February 26
Preprocessing
March 5
ETL
March 12 In-Memory Dataset
March 19 Local SQL
March 26 BDE to InterBase Migration

See you online!

"RasterrainObjPas" - Simple Ray Tracer in Object Pascal

I always wanted to implement a ray tracer in my favourite Object Pascal programming language. The thing is that it is not trivial, especially when you start reading books like "Physically Based Rendering" you realize that implementing a ray tracer might take a lot of time and work.

Recently on YouTube I have come across a serie of 9 episodes "Raytracer from Scratch in C++" by Caleb Piercy. In these shorter and longer movies you can see the process of writing the ray tracer C++ console Windows application that generates a bmp file with a nice image from the very beginning of setting up the project until the fully functional program. Caleb uses a simple code editor and a makefile to build his application.

The original C++ source code of this program is available as open source from Sourceforge. The project is called "rasterrain".

I have decided to give it a try and translate "rasterrain" project to Object Pascal with Delphi XE7.

The first step was to create in C++Builder XE7 a console project and move over to it the original C++ code from SourceForge.

Delphi XE7 (since version XE6) has a dedicated unit called "System.Math.Vectors" that defines classes, routines, types and variables for using vectors and matrixes. Especially useful in the context of implementing a ray tracer is TPoint3D record type that contains the most important linear algebra routines like dotProduct, crossProduct and so on.

The second useful code for implementing a ray tracer are global procedures in the "FMX.Types3D" unit including: RayCastCuboidIntersect, RayCastEllipsoidIntersect, RayCastPlaneIntersect, RayCastTriangleIntersect and RayCastSphereIntersect.

Another very useful type for working with color is the TAlphaColorF record type defined in System.UITypes namespace that stores R,G,B and A information as float values and defines a number of useful operations like adding two colors and so on.

Initially I started from using these prebuilt Delphi types, but quickly realized that it gets complicated not only to translate from C++ to Object Pascal, but also rewriting a lot of code. At the end I have decided to try to mimic C++ code as match as possible in Object Pascal.

The "RasterrainObjPas" is made up of two projects: one multi-device FireMonkey and the second Windows VCL. Both projects are using the same "TSimpleRayTracer" class defined in the "uSimpleRayTracer" unit. The actual ray tracer Object Pascal code does not contain any GUI-specific code and can be used in VCL, FireMonkey or even in a console app. The VCL project can be compiled for Windows only and FireMonkey can be built not only for Windows, but also for Mac, iOS and Android.

Simple Ray Tracer in Object Pascal is available for download from Embarcadero Code Central and the project is called "RasterrainObjPas".

The ray tracer has a very simple interface. The "RGBType" is a platform-agnostic data structure for exchanging color information. The actual color is stored as a record with three float values, for red, green and blue intensities.

type
  RGBType = record
    r, g, b: Double;
  end;
  TSimpleRayTracer = class
  private
    //.. private declaration
  public
    constructor Create(aWidth, aHeight: integer; aAntiAliasingLevel: integer = 1);
    destructor Destroy; override;
    function getWidth: integer;
    function getHeight: integer;
    function getPixelData(x, y: integer): RGBType;
    procedure CalculatePixelColors;
  end;

In the constructor you can specify the size of the image to be generated, including the anti-aliasing level, which is by default "1", which means no anti-aliasing. After constructing an instance of the ray tracer you need to call its "CalculatePixelColors" procedure that calculates colors of every pixel and store them in an internal array of RGB values that can be read using "getPixelData" method that takes x, y coordinates of a pixel and returns "RGBType" value. This can be used to create either a FireMonkey bitmap or a VCL bitmap for display and this is the job of "TRendererFMX" and "TRendererVCL" classes that encapsulate the TSimpleRayTracer class and provide "DoRender" functions that return either a VCL or FireMonkey bitmaps.

Here is the implementation of the FireMonkey "renderer" that converts platform-neutral color information from simple ray tracer class into a FireMonkey bitmap to be displayed in a multi-device application.

unit uRendererFMX;

interface

uses System.UITypes, FMX.Graphics, uSimpleRayTracer;

type
  TRendererFMX = class
  private
    FSimpleRayTracer: TSimpleRayTracer;
    function GetPixelColor(x,y: integer): TAlphaColor;
  public
    constructor Create(aWidth, aHeight: integer; aAntiAlias: integer = 1);
    destructor Destroy; override;
    function DoRender: TBitmap;
 end;

implementation

{ TRendererFMX }

constructor TRendererFMX.Create(aWidth, aHeight: integer; aAntiAlias: integer = 1);
begin
  FSimpleRayTracer := TSimpleRayTracer.Create(aWidth, aHeight, aAntiAlias);
end;

destructor TRendererFMX.Destroy;
begin
  FSimpleRayTracer.Free;
  inherited;
end;

function TRendererFMX.DoRender: TBitmap;
var bmp: TBitmap; data: TBitmapData; w,h,x,y: integer; c: TAlphaColor;
begin
  FSimpleRayTracer.CalculatePixelColors;
  w := FSimpleRayTracer.getWidth;
  h := FSimpleRayTracer.getHeight;
  bmp := TBitmap.Create;
  bmp.Width := w;
  bmp.Height := h;
  bmp.Map(TMapAccess.Write, data);
  try
    for x := 0 to w - 1 do
      for y := 0 to h - 1 do
      begin
        c := GetPixelColor(x, h-y);
        data.SetPixel(x, y, c);
      end;
  finally
    bmp.Unmap(data);
  end;

  Result := bmp;
end;

function TRendererFMX.GetPixelColor(x, y: integer): TAlphaColor;
var c: RGBType; colorF: TAlphaColorF;
begin
  c := FSimpleRayTracer.getPixelData(x, y);
  colorF := TAlphaColorF.Create(c.r, c.g, c.b);
  Result := colorF.ToAlphaColor;
end;

end.

And here is the code in the FireMonkey form that displays the bitmap in an image control and shows how much time it took to generate the image.

uses uRendererFMX, System.Diagnostics;

procedure TFormRenderFMX.btnRenderClick(Sender: TObject);
var sw: TStopwatch; r: TRendererFMX; bmp: TBitmap;
begin
  LabelTime.Text := 'Rendering... Please wait.';
  self.Invalidate;
  Application.ProcessMessages;

  sw := TStopwatch.StartNew;
  r := TRendererFMX.Create(round(Image1.Width), round(Image1.Height), round(TrackBarAntiAliasingLevel.Value));
  bmp := r.DoRender;
  Image1.Bitmap.Assign(bmp);
  sw.Stop;
  LabelTime.Text := IntToStr(sw.ElapsedMilliseconds) + ' msec (' + IntToStr(sw.ElapsedTicks) + ' ticks)';
end;

The VCL renderer class is very similar to FireMonkey and is using scan-line access for best performance.

unit uRendererVCL;

interface

uses VCL.Graphics, uSimpleRayTracer;

type
  TRendererVCL = class
  private
    FSimpleRayTracer: TSimpleRayTracer;
  public
    constructor Create(aWidth, aHeight: integer; aAntiAlias: integer = 1);
    destructor Destroy; override;
    function DoRender: TBitmap;
  end;

implementation

uses System.Types;

{ TRendererVCL }

constructor TRendererVCL.Create(aWidth, aHeight, aAntiAlias: integer);
begin
  FSimpleRayTracer := TSimpleRayTracer.Create(aWidth, aHeight, aAntiAlias);
end;

destructor TRendererVCL.Destroy;
begin
  FSimpleRayTracer.Free;
  inherited;
end;

function TRendererVCL.DoRender: TBitmap;
var bmp: TBitmap; CurrRow, OffSet: integer; x,y: integer;
  pRed, pGreen, pBlue, pAlpha: PByte; c: RGBType; h: integer;
begin
  FSimpleRayTracer.CalculatePixelColors;
  bmp := TBitmap.Create;
  bmp.PixelFormat := pf24bit;
  bmp.Width := FSimpleRayTracer.getWidth;
  bmp.Height := FSimpleRayTracer.getHeight;
  h := FSimpleRayTracer.getHeight;
  CurrRow := Integer(bmp.ScanLine[0]);
  OffSet := Integer(bmp.ScanLine[1]) - CurrRow;

  for y := 0 to bmp.Height - 1 do
  begin
    for x := 0 to bmp.Width - 1 do
    begin
      pBlue  := pByte(CurrRow + x*3);
      pGreen := pByte(CurrRow + x*3 + 1);
      pRed   := pByte(CurrRow + x*3 + 2);
      pAlpha := pByte(CurrRow + x*3 + 3);
      c := FSimpleRayTracer.getPixelData(x, h-y);
      pBlue^  := round(c.b * 255);
      pGreen^ := round(c.g * 255);
      pRed^   := round(c.r * 255);
      pAlpha^ := 255;
    end;
    inc(CurrRow, OffSet);
  end;

  Result := bmp;
end;

end.

The VCL form code is almost identical to FireMonkey:

uses uRendererVCL, System.Diagnostics;

procedure TForm17.btnRenderClick(Sender: TObject);
var sw: TStopwatch; r: TRendererVCL;
begin
  LabelTime.Caption := 'Rendering... Please wait.';
  self.Invalidate;
  Application.ProcessMessages;

  sw := TStopwatch.StartNew;
  r := TRendererVCL.Create(round(Image1.Width), round(Image1.Height), TrackBarAnitAlias.Position);
  Image1.Picture.Assign(r.DoRender);
  sw.Stop;
  LabelTime.Caption := IntToStr(sw.ElapsedMilliseconds) + ' msec ('
    + IntToStr(sw.ElapsedTicks) + ' ticks)';
end;

On both forms there are also trackbars to select anti-aliasing. In the original C++ code the value for controlling anti-aliasing is hardcoded to "1", which means that for calculating the color of the pixel there is just one ray used. The higher the "anti-aliasing" level, the more rays are used to calculate color. For example for the value of 2 there are 4 rays used and the resulting color is the average. For the value of 3 there is an internal 3×3 grid, which means 9 rays and so on. The higher the anti-aliasing level, the actual color calculation takes longer, but the quality is better. The image embedded in this post has been rendered with anti-aliasing level 10. Which means there were 100 rays used to calculate every pixel and on my virtual machine it took around 40 seconds.

I’m not going to go deeply into the internals of the actual TSimpleRayTracer class, because its functionality is discussed in a very detailed way in original YouTube episodes "RayTracer from Scratch in C++".

The full source code of Simple Ray Tracer in Object Pascal can downloaded from the Embarcadero CodeCentral.

You can also get the source code from GitHub at https://github.com/pglowack/RasterrainObjPas

"Modernize Your VCL App Today!" webinar recording and demos

It was fun to do the "Modernize Your VCL App Today!" webinar:-)

During the session I have promised to make the recording and demos source code available.

The recording is rather big (548MB) and can be downloaded from here and demos source code has been uploaded to the Embarcadero CodeCentral.

  • mastapp. Original Delphi 7 BDE demo project
  • MarineAdventures. Mastapp upgraded to Delphi XE7 with VCL styles and JumpList component
  • StylingDemo1. Demo illustrating working with "StyledElements" property for customizing styled VCL controls.
  • JumpListFiles. Demo of the new XE7 TJumpList component
  • MetroGrid1. Demo showing VCL Metropolis UI with user selectable VCL styles.
  • Ribbon. Demo project showing Ribbon UI.
  • ParallelTasksAndFutures. Standard Parallel Programming Library demo illustrating syntax for tasks and future
  • ParallelMandelTest. Mandelbrot fractal generation application with added support for parallel "for" loop
  • FireDACResource. Enterprise Mobility Services demo with FireDAC.

The session was logically divided into two parts. The first one was about using the latest XE7 technologies to modernize the application user interface, application logic and data access. The second one was on moving to multitier, scalable architectures like EMS and DataSnap.

"Modernize Your VCL Applications Today" webinar, Dec 16th, 11am CET

If you have an existing VCL application and you want to modernize it to the latest technologies included in Delphi XE7, C++Builder XE7 and RAD Studio XE7 - this webinar is for YOU!

Next week on Tuesday, December 16th, 11am Amsterdam time, I’m going to do a live, demo-oriented technical free webinar that will cover working with VCL styles, new Parallel Programming Library, migrating to FireDAC database access framework and building scalable, multitier solutions with DataSnap and Enterprise Mobility Services (EMS) technologies.

I have been doing "VCL Modernization" live presentations in previous few weeks in a number of different cities in Europe. If you have missed the live event, now it is the opportunity to see it online!

That’s incredible how many applications have been written in the past 20 years with Delphi using the VCL, the Visual Component Library. These applications do all kinds of things and typically interact with databases. In this session I’m going to cover how to move these projects to the latest technologies at different levels of a typical application from user interface, through application logic to database access. We are also going to see what it takes to move to mobile technologies and multitier architectures. The day after my webinar there will be Object Pascal master session from Marcu Cantu, so I will not be going to deep into the new features of the programming language of Delphi and focus on everything else;-)

The webinar is free, it will take approximately an hour and will be followed with the Q&A session, so anybody will be able to ask questions and hopefully get answers!

In order to join the free webinar you need to register here!

Making "Color to Gray" conversion algorithm parallel

One of the most important new features in RAD Studio XE7 is new "Parallel Programming Library". It is available for both Object Pascal and C++, and for both VCL and FireMonkey, multi-device projects.

During the recent CodeRage 9 virtual conference there were two very informative sessions on parallel programming from Allen Bauer and Danny Wind.

A few days ago I was doing VCL application modernisation workshop in Utrecht and thought it would be good to take an existing VCL application and see what it takes to make it parallel.

A few years ago I was playing with different ways of accessing individual pixels in the VCL bitmap on the example of "Color to Gray" algorithm. Clearly using bitmap’s scanline is a few levels of magnitude faster than access through "Pixels" property. The differences in speed are discussed here: http://blogs.embarcadero.com/pawelglowacki/2010/04/15/39051

In the "color to gray" algorithm the color of every pixel is calculated independently from each other is a nested "for" loop. This is a perfect case where we can benefit from refactoring the code to use a parallel loop instead.

Let’s consider a simple example of an existing code that we would like to convert:

procedure ToGrayPixelsNoParallel(aBitmap: Graphics.TBitmap; cg: TColor2Grayscale = c2gLuminosity);
var w, h: integer;
begin
  if aBitmap <> nil then
    for h := 0 to aBitmap.Height - 1 do
      for w := 0 to aBitmap.Width - 1 do
        aBitmap.Canvas.Pixels[w,h] :=
          ColorToGray(aBitmap.Canvas.Pixels[w,h], cg);
end;

Here we have two nested "for" loops. On my machine I have only two virtual cores and on a physical one - just four. That is why there is no point in turning both loops to "parallel". We only want to convert the "outer" one. Here is the code after "parallelization":

procedure ToGrayPixelsParallel(aBitmap: Graphics.TBitmap; cg: TColor2Grayscale = c2gLuminosity);
var h: integer;
begin
  if aBitmap <> nil then
    TParallel.For(0, aBitmap.Height-1,
      procedure(h: integer)
      var w: integer;
      begin
        for w := 0 to aBitmap.Width - 1 do
          aBitmap.Canvas.Pixels[w,h] :=
            ColorToGray(aBitmap.Canvas.Pixels[w,h], cg);
      end
    );
end;

The key thing to look for is using local variables. Notice that I had to move "w: integer" local variable into the body of the anonymous method that is being executed. If I would not do it, the same variable would be shared by different threads of execution leading to errors.

And yes. The parallel versions of both "pixels" and "scan line" color to gray are working as expected on average two times faster on my two virtual cores inside of my virtual Windows machine running on Mac.

The source code of the test "PixelsVsScanLineParallelToGray" Delphi XE7 VCL project is available for download from Embarcadero Code Central.

VCL FireDAC Workshop in Warsaw

Good fun!

I have promised a while ago to stop blogging here, but it is going to be a parallel pattern for a while;-)

http://community.embarcadero.com/index.php/blogs/entry/modernize-your-vcl-database-apps-with-firedac-and-delphi-xe7-workshop-in-warsaw

Bad Behavior has blocked 2 access attempts in the last 7 days.

Close