Tuesday, 21 June 2011

Building my own Delphi Physics Engine part VII

After several weeks working on my TDPE I think I managed it to get the desired outcome and now the displayed items show more realistic features. In my previous versions, neither angular velocity nor mass was interacting in terms of moving an object and now, using different mathematical algorithms, the gravity and angular velocity are considered for every item. That means that as soon as a collision is originated, the resultant force will lean back or forward the object and it will be rotating or moving until the forces of the system reach a value close to zero.
This new approach has included a massive refactoring of the existing code to cope with this new behaviour that will deliver spectacular performances. During the following weeks I'm going to  focus on the cutting tool as now I only have to extent the 4-edges collision object to n-edges. Once I have the n-edges collision object then I would be able to generate small chunks of it and each piece would have its own behaviour giving you the feeling that the object has really been broken.


As it's shown in the image, when most or more than a half of the object is out of the base (in blue), the red box should lean forward and fall according to the laws of physics (falling using rotation instead of falling straight how it was before in previous versions).

The following video will show the results of applying the latest algorithms to my Engine:


Enjoy the video!.

Get the latest executable here: ThundaxBallDemo v1.349.
If you want to drop a box, press 'd' and a new red box will fall.

Related links:

Wednesday, 15 June 2011

Delphi Compiler version directives

Due to recent release of DelphiXE, here you can find a extended list of delphi compiler version directives that will help you to upgrade your projects. These are very helpful If you plan on writing Delphi code that should work with several version of the Delphi compiler.

{$IFDEF VER80}  - Delphi 1
{$IFDEF VER90}  - Delphi 2
{$IFDEF VER100} - Delphi 3
{$IFDEF VER120} - Delphi 4
{$IFDEF VER130} - Delphi 5
{$IFDEF VER140} - Delphi 6
{$IFDEF VER150} - Delphi 7
{$IFDEF VER160} - Delphi 8
{$IFDEF VER170} - Delphi 2005
{$IFDEF VER180} - Delphi 2006
{$IFDEF VER180} - Delphi 2007
{$IFDEF VER185} - Delphi 2007
{$IFDEF VER200} - Delphi 2009
{$IFDEF VER210} - Delphi 2010
{$IFDEF VER220} - Delphi XE

Related links:

Tuesday, 14 June 2011

A "moral operating system"

Damon Horowitz calls for a "moral operating system". At TEDxSiliconValley, Damon Horowitz reviews the enormous new powers that technology gives us: to know more -- and more about each other -- than ever before. Drawing the audience into a philosophical discussion, Horowitz invites us to pay new attention to the basic philosophy -- the ethical principles -- behind the burst of invention remaking our world. Where's the moral operating system that allows us to make sense of it?
Source: TED.
Enjoy the video!.

OLE Automation with Delphi part II

Going on with my previous post (OLE Automation with Delphi part I) where I was able to use the invocation of the "Word.Application" service using COM. In this post I am going to show you how to detect if a service is available using OLE Automation. First of all, I'm going to give you a brief overview of the windows Registry and where are all these COM class objects allocated, and then I will move forward to show the Delphi code that is used for this purpose.

COM class objects are identified by a CLSID key:
A CLSID is a globally unique identifier that identifies a COM class object. If your server or container allows linking to its embedded objects, you need to register a CLSID for each supported class of objects
source: msdn

If we have installed Microsoft Word and look for "Word.Application" inside the registry, we will find the following information under \HKEY_CLASSES_ROOT\Word.Application:

This entry has the CLSID key = {000209FF-0000-0000-C000-000000000046}. This CLSID key has been set when the component was registered. We can look it up and check what executable or routine is invoking in the next key entry: HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{CLSID}.


As we can see, it shows the path of Microsoft word and with the option /Automation. Now that we know how to deal with the windows registry and how are set out CLSID keys, let's move on how to use this information with Delphi.

Check if the COM Class Object is registered:
To ensure that the service is available, we can use the OLE32 methods available through ActiveX and ComObj units.

unit Activex;

function CLSIDFromProgID;               external ole32 name 'CLSIDFromProgID';

Example of use:

uses
    ActiveX, ComObj;

procedure TForm1.CheckCLSIDClick(Sender: TObject);
var
    clsid: TCLSID;
    sCLSID: string;
    result: hResult;
begin
    // initialize COM
    CoInitialize(nil);

    // Get CLSID from Microsoft Word
    result := CLSIDFromProgID('Word.Application', clsid);
    sCLSID := GUIDToString(clsid);
    try
        OleCheck(result);
        ShowMessage('Class Word.Application recognized with CLSID ' + sCLSID);
    except
        on e: EOleSysError do
        begin
            ShowMessage('Class Word.Application not recognized CLSID ' + sCLSID);
        end;
    end;

    // deinitialize COM
    CoUninitialize;
end;

Invoking the COM Class Object:
Now that we are sure the COM Class is registered, we can cater the CoCreateInstance method to invoke the class with the proper context properties. dwClsContext is the context in which the code that manages the newly created object will run. The values are taken from the enumeration CLSCTX.
We can find this enumerators in the ActiveX unit with the following values:
{$EXTERNALSYM CLSCTX_INPROC_SERVER}
  CLSCTX_INPROC_SERVER     = 1;
  {$EXTERNALSYM CLSCTX_INPROC_HANDLER}
  CLSCTX_INPROC_HANDLER    = 2;
  {$EXTERNALSYM CLSCTX_LOCAL_SERVER}
  CLSCTX_LOCAL_SERVER      = 4;
  {$EXTERNALSYM CLSCTX_INPROC_SERVER16}
  CLSCTX_INPROC_SERVER16   = 8;
  {$EXTERNALSYM CLSCTX_REMOTE_SERVER}
  CLSCTX_REMOTE_SERVER     = $10;
  {$EXTERNALSYM CLSCTX_INPROC_HANDLER16}
  CLSCTX_INPROC_HANDLER16  = $20;
  {$EXTERNALSYM CLSCTX_INPROC_SERVERX86}
  CLSCTX_INPROC_SERVERX86  = $40;
  {$EXTERNALSYM CLSCTX_INPROC_HANDLERX86}
  CLSCTX_INPROC_HANDLERX86 = $80;

Example of use:
If we take a look again at the Registry picture above, we will notice that our COM Class uses a LOCAL_SERVER context, and that's the value that we will have to set in the API method.

This simple example will use the COM CLSID to invoke Microsoft Word and open it:

uses
    ActiveX, ComObj, Ole2;
{$R *.dfm}

procedure TForm1.InvokeCLSIDClick(Sender: TObject);
var
    clsid: TCLSID;
    sCLSID: string;
    result: hresult;
    localCLSCTX: Integer;
    IWordApp: IUnknown;
    dispIWord: IDispatch;
    AttrName: POleStr;
    paramArgument: VARIANTARG;
    disparam: DISPPARAMS;
    dispIDs: TDispID;
    did: TDispID;
begin
    // initialize COM
    CoInitialize(nil);
    localCLSCTX := CLSCTX_LOCAL_SERVER;
    try
        // Get CLSID from Microsoft Word
        result := CLSIDFromProgID('Word.Application', clsid);
        // sCLSID := GUIDToString(clsid);
        OleCheck(result);
        // create Microsoft Word instance
        result := CoCreateInstance(clsid, nil, localCLSCTX, IID_IUnknown, IWordApp);
        OleCheck(result);
        // get IDispatch interface of received object
        IWordApp.QueryInterface(IID_IDispatch, dispIWord);

        // Invoke Microsoft Word
        AttrName := 'Visible';
        paramArgument.vt := VT_BOOL;
        paramArgument.vbool := true;
        disparam.cArgs := 1;
        disparam.rgvarg := @paramArgument;
        dispIDs := DISPID_PROPERTYPUT;
        disparam.cNamedArgs := 1;
        disparam.rgdispidNamedArgs := @dispIDs;

        dispIWord.GetIDsOfNames(GUID_NULL, @AttrName, 1, LOCALE_SYSTEM_DEFAULT, @did);
        result := dispIWord.Invoke(did, GUID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, disparam, nil, nil, nil);
        OleCheck(result);
    except
        on e: EOleSysError do
        begin
            ShowMessage('Class Word.Application not found CLSID ' + sCLSID);
        end;
    end;
    // release unused objects
    dispIWord.Release;
    IWordApp.Release;
    // deinitialize COM
    CoUninitialize;
end;


Related links:

Wednesday, 8 June 2011

Delphi Certification program

Embarcadero released yesterday the "Delphi Certification Program" where you can get one of the Delphi certificates to distinguish yourself from other professionals.

There are two certificates available:

For the Delphi developer certification, if you are a registered Delphi XE user or RAD Studio XE user, you are eligible to take the certification test free of charge. As Pawel Glowacki told us in the Embarcadero Live Event, these certificates are to certify your skills and to stand out from the rest. I have been looking forward to them, and now I'm eager to start taking the tests!.

The certification test covers the following areas of knowledge:
  • Delphi Fundamentals
  • Data types, variables, and Constants
  • Procedures and Functions
  • Classes and Objects
  • Object Interfaces
  • Generics, Attributes and Anonymous Method
  • Database Concepts
  • Standards Routines and I/O
  • Libraries and Packages
  • Memory Management
  • Exceptions and Assertions