Home > Delphi, OP4JS, Smart Mobile Studio > Firemonkey like 3D for all Smart Mobile Elements

Firemonkey like 3D for all Smart Mobile Elements

火災猿はクールです

火災猿はクールです

Well, I might as well let the monkey out of the bag. For some time now I have spent a chunk of my spare time exploring the idea of adding 3D to Smart Mobile Studio. Not unlike what Firemonkey provides for Delphi these days. Naturally 3D and Javascript is pretty heavy duty stuff, completely dependent on webGL right? Well not really. In fact, with clever use of CSS Smart Pascal is (or will be) capable of doing most of the practical 3D stuff you find in Firemonkey. But yes, if your app can use webGL (depending on where it runs) that is the absolute best.

What I mean with practical 3D is simply that around 90% of what Firemonkey introduces is, well, a complete waste of time in a business application. I dont mean this in any negative way, I love Delphi and Firemonkey is a fantastic RTL and framework. But a rotating form or spreadsheet is .. well, perhaps not what you want when crunching numbers on a tax report due yesterday.

But Firemonkey really comes into it’s own on mobile devices, where you are almost expected to have widgets that wobble, rotate and gives visual feedback on every touch. So I’m not dizzing Firemonkey here — I am simply saying that for serious scientific or business apps – it’s out of place.

3D and Smart Mobile Studio

CSS3 have some neat features, like being able to position elements in 3d space. So using CSS you can not only animate elements between visual states (keyframe animations), you can apply those animations in 3D space. Meaning that you can rotate a DIV tag (the primary container Smart Pascal custom-controls manages) in X, Y and Z vectors. Here is a little example of a CSS animated cube.

If you define backface-visibility as active, your elements become semi-transparent, and elements behind your element (in 3d space) becomes visible. In the golden days of Amiga demo programming, we called that “glenz vectors”.

Partial classes, the death of plugins

So, the challenge at hand for me, is to provide full 3d support without messing up the RTL (which should be considered as the seed-stone and foundation for SMS apps, bordering on sacred). The only way to do this is to use partial classes. If you dont know what that is you can read up on the topic — but in general it means that you can extend a class anywhere by adding the Partial keyword. And voila, all the new features you add to your partial class, becomes a part of the class you extend.

In other words, plugins have no place in SMS because partial classes completely removes the need for them. A plugin could never really extend a class in the same way anyhow – so it’s no competition at all.

Using the force

Before you start to play around with effects, you really should download and install my QTX library. This is hosted on Google code and contains whatever classes and examples I post here. So use SVN and check it out into your $SMS/Libraries folder (! important !) so the IDE automatically locates the files.

The library also adds a wealth of “missing” tidbits and stuff to the RTL (safely, without messing up anything) so it should be considered “a must have” for all SMS hackers out there.

Simple 3d

Right. For simple 3d effects that you can apply to anything (buttons, lists, checkboxes, labels or whatever) you simply add the unit qtxTransformController (which is in the QTX library). This unit contains a class called TQTXTransformController. You can create an instance of this class, proving the handle of the control you want to play with — and voila, you can rotate your element in whatever X, Y, Z vector you want.

procedure TForm1.AnimateStuff;
var
  mObj: TQTXTransformController;
begin
  mObj:=TQTXTransformController.Create(w3button1.handle);
  mObj.x:=100;
  mobj.y:=100;
  mObj.z:=-50;
  mObj.update;
end;

But all of this is tiresome work. I mean, we cant create transform controllers for each and every element right? It may be kosher for games where you have a fixed number of sprites, but it would take ages to manage for ordinary apps. So my mission at the moment is to merge TQTXTransformController with TW3CustomControl using a partial class — thus exposing the 3D framework directly

Digging into it

Perspective is depth

Perspective is depth

But there are real challenges. For 3D perspective to work properly, it has to be defined by the container. In other words, if you want to rotate a button using the X Vector around it’s own axis — the perspective (Z vector) of the container defines it. In other words, the depth perception is set in the container tag, typically 1000 — meaning that you can then rotate your button and it can have a depth into space of 1000 pixels. Anything deeper looks.. well, a bit 80’s spaceship weirdo demo-ish.

The best way to think about this — is like a tub of water with a plank of wood floating on the surface. The Z vector of the parent defines how deep the tub is, while the X, Y and Z vectors of the element defines how deep you push the plank, and in what end you apply force.

So X = -50 means that you push the left side of the plank down by 50 pixels. X = 50 means that you push the right edge of the plank down by 50 pixels (at which point the left side of the plank goes up by the same amount). The Z factor for the element is how deep the in the water the plank is held.

-webkit-transform: rotateX(90deg);
transform: rotateX(90deg);

The above CSS will look.. well, flat, unless we apply this to the container elements (form, panel etc..):

-webkit-perspective: 1000px;
perspective: 1000px;

Once you apply that snippet of CSS to the container, suddenly the element gains depth and truly looks 3D. We also want the elements to preserve their 3D modifications after an effect has been applied, which is what the “preserve 3d” property is all about:

-webkit-transform: rotateX(90deg);
transform: rotateX(90deg);
transform-style: preserve-3d;

So what is the problem? Well, if you already have a CSS3 GPU effect running on the container – there is no telling what happens. It’s a bit like flipping a coin which effect is annulled by the browser. Hence we need to be clever about this. We need a easy to use, lightweight, ad-hoc framework which is capable of handling possible conflicts, and also – in some cases, merge effects on elements that can handle multiple adjustments.

If you want to see what can be achieved by JavaScript and 3D, check out this demo — which used webGL (sadly, because we want to avoid dependencies on that — but still support it for desktop code). Before we run, we have to make sure we walk properly first. A three.JS port to Smart Mobile Studio is available at Andre’s github repo. Sadly I dont remember the link right now, but will post it later.

Three JS, probably the best 3D library out there

Three JS, probably the best 3D library out there

Anyways, while I research the future of Object Pascal in the world of JavaScript — use my 3d controller to play around with your GUI’s. And dont forget to apply perspective to your containers! Be it the form or a TW3CustomControl (which really is the best way to do this!).

Advertisements
  1. davidberneda
    August 21, 2014 at 4:25 pm

    Three.js can also be a good alternative imo, caniuse.com shows webgl more and more available. http://www.steema.com/files/public/teechart/html5/v2012.12.14.1.4/demos/canvas/webgl/index.html

    • Jon Lennart Aasenden
      August 21, 2014 at 7:02 pm

      Yes i mention that at the end of the article. SMS already have a wrapper for it, but dont have the github URL right now, so i’ll post it later. Also, the batmobile + link at the bottom is pure three.js 🙂

  1. No trackbacks yet.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: