Skip to content

TMS WEB Core 3D

TMS WEB Core 3D component library can be used to create impressive 3D WebGL applications in Delphi. It consists of several components to display interactive 3D Charts and Models in a Web Application. These components internally use WebGL through Three.js, an open source, cross-browser JavaScript library. The best thing is that one need not know WebGL or Three.js in order to make basic 3D applications with these components. At the same time, if the need arises, direct Three.Js API calls can be made in Delphi code through a JS interface library provided for the purpose.

Your first 3D Chart application

Create a standard TMS Web Application in the Delphi IDE by choosing File, New, Other, TMS Web Application.

A new web form is created. Go to the Tool Palette and select the TWebThreeJsChart component from the “TMS Web 3D” section and drop it on the web form.

Now the only thing remaining is to include the proper Three.js library file. Right-click on the Project and select “Manage JavaScript Libraries.”

Choose the “Three JS (3D)” library and click OK

Save and Run the project. You will see a Default Chart come up in the browser. Try to rotate the chart with the mouse and zoom with the mouse wheel. You get that interactive functionality out of the box, without writing any code!

You can now customize the data series for this chart in the code of the form as per your requirement. For some sample code, please see the demo project under the TMS folder Demo, 3D, Chart. The demo code is discussed in the next section.

3D Business Chart Applications

As shown above, the TWebThreeJsChart component can be used to create 3D Business Chart applications that draw bar, line or area charts.

The 3D Bar Chart Demo

After creating a quick 3D chart application as shown in the previous section, the next step is to try and understand the customization code in the Chart Demo so that you can code your own custom data series for a similar 3D bar chart. First of all, open the Chart Demo under the TMS folder Demo, 3D, Chart and run it. Move the mouse over the chart items and you will see them glow with a Text Popup showing the value. Try out various features given in the Demo before we discuss the code.

The Terminology for Axes

Before coding the data series, you will need to understand how each axis is named. The above picture shows the name of each Axis.

Creating the Data Series object

Please look at the Web Form code of the procedure LoadSampleSeries1.

var
  aSeries: TThreeJsChartSeries;
begin
  aSeries := TThreeJsChartSeries.Create(
          TJSArray.New('East', 'West',
          'North', 'South'),
          TJSArray.New('Q1', 'Q2', 'Q3',
          'Q4')
          );

The constructor of the Series object expects 2 parameters as the Axis Labels to be passed in two JS Arrays: 1. Legend Axis Labels 2. Category Axis Labels Then the data is added in the form of each Legend Row as an array in the following code. The Demo uses hard coded data but you can have your own logic to obtain the data for each Legend row.

aSeries.addLegendRow('East',
 TJSArray.New(41834, 52835, 46563,
 60184));
aSeries.addLegendRow('West',
 TJSArray.New(48842, 62964, 54243,
 73796));
...
The rest of the Series set up code is easy to understand:
aSeries.valueAxisMarkMaximum := 100000;
aSeries.valueAxisMarkStep := 20000;
aSeries.valueFormatFloat := '$#,##0';
aSeries.valueAxisFormatFloat := ''; //use the above
aSeries.Title := 'Sales by Region';
aSeries.ValueAxisTitle := 'Quaterly Sales';
aSeries.LegendAxisTitle := 'Regions';
aSeries.CategoryAxisTitle := 'Quarters';
threeJsChart.Series := aSeries;

Notable points:

  • The Format to show values on the chart items can be different from the format to show values on the Value Axis marks. But the above code uses the same format for both.
  • The series object is finally assigned to the Series property of the Chart component. The above Load procedure is called from the WebFormCreate event and then the chart is displayed by the following code.
    threeJsChart.clearChart;
    threeJsChart.createChart;
    

The chart component is smart enough to decide on proper axes length and marks based on the data. But you can set the dimensions of items too, resulting in a bigger or smaller chart area.

Other features shown in the Demo

You can run and explore the Chart Demo to see many other features demonstrated:

  • Built in objects: Many built in objects like the Camera, Spotlight, etc are automatically added by the component. You don’t have to write any code.
  • Interactive Rotation and Zoom with the mouse and mouse wheel: You get this functionality out of the box, without writing any code.
  • Choice of Chart Type: Chart items can be shown as Bars, Cylinders, Cones, Lines or Areas.
  • Auto colors: Colors are assigned automatically to Legend rows. You can specify custom colors too.
  • Dimension Properties for items: Item Width, Space and Plot Width (for Line and Area charts) can be changed. The dimensions are in WebGL units. The component is smart enough to determine the length of bottom 2 axes automatically based on the item dimensions. But you can override the default length of Value Axis by a separate property.
  • Transparency of Chart Items: can be set with additional Opacity property.
  • Optional Legend display: can be specified to associate colors with Legend items.
  • Auto Marking of Value Axis: The demo code does not use this feature by default. But you can switch on this checkbox to see its effect. This is a smart feature that determines the marks on the Value scale based on the data.

Other Niceties available:

  • Auto rotate axis labels to always face the Camera
  • Show value popups on all items
  • Transparency and opacity control

Events

The following events are available:

  • Interaction with Items: OnItemClick, OnItemExit, OnItemDblClick, OnItemMouseEnter, OnItemMouseLeave, OnItemMouseMove
  • Interaction with other areas of the chart: OnClick, OnDblClick For example, the Demo uses the above events to show features like displaying value popups on items and glowing of items when the mouse is moved over the items or when the items are clicked.

For example, the Demo uses the above events to show features like displaying value popups on items and glowing of items when the mouse is moved over the items or when the items are clicked.

3D Math Chart Applications

The component TWebThreeJsMathChart is available to create 3D Math Chart applications that draw Scatter or Surface charts.

The 3D Scatter Chart Demo

Open this Demo under the TMS folder Demo, 3D, Scatter and run it.

The Terminology for Axes

Before coding the data series, you will need to understand how each axis is named in a Math chart. This is different from the bar chart seen earlier that uses business terminology. The above picture shows the name of each Axis.

Creating the Data Series object

Please look at the Web Form code of the procedure LoadSampleSeries1. The Series class is TThreeJsMathChartSeries. The code that passes X, Y, Z data to the series is:

aSeries.addData(x, y, z, psSphere, name,
 aPointSize, aPointColor)
In addition, the shape of the scatter point, its name, its size and color can be passed. The rest of the code to set the Series and to create the chart is similar to the earlier Chart Demo.

Other features shown in the Demo

Other features demonstrated are similar to those described for the earlier Chart Demo except for the following differences:

  • Auto Marking feature now determines the length and scale marks for all 3 axes based on the Series data. The Demo uses this feature. This feature saves considerable effort for a typical Math Chart application to pre determine and set the length and scale marks for each axis.

  • Improved Legend: The Legend in the scatter chart shows the shape of the point in addition to the color. The Events used in the Demo are also similar to those described for the earlier Chart Demo.

The 3D Surface Chart Demo

This demo demonstrates the features of TWebThreeJsMathChart component used to draw a surface chart based on an Equation. Hence, it is called a Parametric Surface Chart. Open this Demo under the TMS folder Demo, 3D, Surface and run it.

How it works

In the Demo, you can select a Surface Equation from a dropdown list to draw the surface chart accordingly. For example, here is another Surface Chart produced by the Demo:

Creating the Data Series object

Please look at the Web Form code of the procedure LoadEquation. The Series class is same as that for earlier Scatter Demo– TThreeJsMathChartSeries. But the procedure to add the data

for surface chart is different:

aSeries.addParametricSurface(xMin, xMax,
 yMin, yMax, resolution, @surfaceCallBack);

The ranges of values for X and Y are passed along with a Delphi Parametric callback function. The Chart component does the following:

  • Generates X and Y values based on the parameters passed
  • For each pair of values, calls back the Parametric function of the application to get the value of Z.

The callback function used in the Demo is:

function TForm2.surfaceCallBack(x, y: double): double;
begin
  case cbSeries.ItemIndex of
    1: Result := abs(x-y);
    2: Result := -x*x - y*y + 6;
    3: Result := sin(x)*x+cos(y)*y;
    4: Result := 2 * sqrt(x*x/3 + y*y/8);
    5: Result := sqrt(abs(1.5 * (x*x/3 - y*y/4) - 6));
    6: Result := 8 * (sin(x) + cos(y));
  else
    Result := x*x + y*y;
  end;
end;
The function uses the index of the drop down list to select an equation and return a Z value accordingly.

Other features shown in the Demo

You can run and explore the 3D Surface Chart Demo to see some more features provided for the Surface chart:

  • Show Wire Frame: The cells of the wire frame depend on the Resolution value.
  • Show Wire Frame Texture: This draws a wire frame texture directly on the colored surface of the chart. With the default high resolution, you may not be able to see this. Try a lower resolution value to see how this works.
  • Use Custom Colors and Texture.

3D PaintBox Applications

The TWebThreeJsPaintBox component lets you create arbitrary 3D Scenes containing often used objects like Cubes, Spheres, Text and more. In fact, these primitives come from the base class and the already created Chart components are great examples of the kind of applications that are possible.

The 3D PaintBox Demo

You can open the PaintBox Demo under the TMS folder Demo, 3D, Paintbox and run it.

The Terminology for Axes

This component uses standard WebGL axes. These are shown in the picture above. You need to provide the positions of objects accordingly. All dimensions and positions are in WebGL units.

The code for adding objects

The objects are added to the scene in the OnCreate event of the Web Form with a code that looks like the following. The initial parameters for each object are dimensions, followed by the a TColor, followed by X, Y, Z position.

// Add a Bar with color $ff7777
anObject := threeJsPaintBox.AddBar( 2, 3, 2, $ff7777, 8, 7, 10);
anObject.name := 'bar1';

// Add a cube
anObject := threeJsPaintBox.AddCube(3, $00FF00, 16, 5, 8);
anObject.name := 'cube2';

// Add a Sphere
anObject := threeJsPaintBox.AddSphere(2, $0000ff, 10, 8, 4);
anObject.name := 'sphere1';
// Add a Cylinder
anObject := threeJsPaintBox.AddCylinder(1,  1, 7, $00ffff, 4, 3.5, 13);
anObject.name := 'cylinder1';

// repaint the box to show new objects
threeJsPaintBox.Invalidate;

There are many more parameters for above functions with defaults, for example, to specify transparency. But the Demo code does not use them and default values are used for those. You can make quite impressive 3D applications by creating objects as shown above. The 3D Chart components discussed earlier are examples of such applications.

Direct Use of the Three.Js API

Object creation methods like “AddCube” return a 3D Object of the type TThreeJsObject3D. Such types are Three.Js objects made available to you in Delphi syntax via the specially coded JS Interface unit “Libthreejs.” The end result is that you can directly use the methods and properties of these objects as documented in Three.Js documentation. For example, to change the position of an object, you will change its “position” property directly, in Delphi code. All the methods that expect a color as a parameter have been modified to use TColor of Delphi for the convenience of Delphi developers even though Three.Js internally uses the Web color codes.

Sample code for Other features

Please run this Demo and inspect the source to see how you can perform these actions on objects in your own code.

  • Built in objects: Many built in objects like the Camera, Spotlight, etc are automatically added by the component. You don’t have to write any code.
  • Interactive Rotation and Zoom with the mouse and mouse wheel: You get this functionality out of the box, without writing any code.
  • Rotation by code: Rotate the whole scene around the origin by RotateLeft and RotateRight methods of the component. The demo uses Rotate trackbars to show this feature.
  • Change Center of Viewing: To make another object’s position as the center of viewing/rotation, use the method SetTargetViewVector and pass the position of another object. This is demonstrated by the button “Set Cube2 as Center of Viewing.”
  • Panning by code: Similarly, you can pan the camera by Pan* methods of the component. The demo shows this feature by the 4 Pan buttons.
  • Zooming by code: Use the ZoomIn method. This is shown by the Zoom trackbar.
  • Save orientation: Suppose you want to save the exact orientation of the scene with respect to the camera and then restore it later. A SaveState method is provided for this purpose. Similarly, a ResetState restores the orientation to a saved state. The Demo shows this feature by “Save Orientation” and “Restore Orientation” buttons.
  • Debugging arrow: Sometimes, you may want to know the exact position of certain invisible objects like the SpotLight and its target. A method ShowDebugArrow is provided for this purpose. The demo shows this feature via the button “Show Arrow from Spotlight to Its Target.”
  • Moving an object: If you have the handle of an object, you can change its position property directly. This is shown by the buttons “Move Spotlight Up/Down” where the object used is the Built In SpotLight object. You can use such code on any object that you have saved as a variable. The bottom trackbars are used in the Demo to move the object selected in the List “Operations on Object.”

Events

The following events are available:

  • Interaction with Objects: OnItemClick, OnItemExit, OnItemDblClick, OnItemMouseEnter, OnItemMouseLeave, OnItemMouseMove
  • Interaction with other areas of the Scene: OnClick, OnDblClick

3D Model Applications

The TWebThreeJsModelBox component lets you create or load arbitrary 3D Models from model files. In addition to the earlier described PaintBox methods, it contains methods to add Obj/Mtl or GLTF models from model files and can Export the scene to GLTF model files.

“ThreeJS Models (3d)” JS Library is required

If you use the TWebThreeJsModelBox component in an application, you should include the JS Library “ThreeJS Models (3d)” by using the same Project right-click menu “Manage JavaScript Libraries” that is described in an earlier section “Your first 3D Chart application.”

The 3D Model Demo

Since this Demo needs to load models from data files, an extra second step is required to copy those files as described below.

  • Open the Model Demo under the TMS folder Demo, 3D, Model.
  • Copy the 2 subfolders from the Data folder of the project to the web output folder.
  • Now build and run the Demo.
  • Select the Model “R2 D2 Robot” at the top and click on “Load Obj/Mtl Object” to get a result similar to the following picture.

The Code to Load OBJ/MTL Models

You will see a code like the following to add objects from OBJ/MTL files:

threeJsModelBox.AddObjectMtl('model-R2D2',
 'r2-d2.obj', 'assets/',
 'r2-d2.mtl', 'assets/',
 'assets/');
The first parameter is the name given to the model followed by the OBJ and MTL model file names and various folders accompanying them.

The code to Load GLTF Model

You will find this in the action code of Load GLTF Model button. The call is AddObjectGltf that is much simpler because only one GLTF file needs to be specified with an optional path for the accompanying folder, often not needed.

Getting the Object in OnObjectLoad event

Note that the loading of the Model is asynchronous and requires internal loading of many other files such as textures. So the above Add methods do not return an Object immediately. Instead, you have to use the event OnObjectLoad that hands over the object to you. There, you can take other actions on the object like rotating it if needed. For example, if you see the code for this event,you will see a particular “Gothic Fence” object being rotated after loading because its default loaded view is horizontal, flat.

Additional features for Models

Auto Position Object after Loading by the method BringObjectInFullView

A third party 3d model object can be of any size. The Three.Js code to properly position the camera so as to bring the object of any size in full view is complicated. Hence, the component implements a method BringObjectInFullViewthat does this job well. This method is used in the Demo’s OnObjectLoad event to bring the object properly in view. You can see the difference made by this auto positioning method by unchecking the option when loading the R2 D2 model. The model is large and if you do not use the above method, you can only see the feet of the Robot after a load. You need to zoom out to see the full Robot which is big.

Additional Lights and Gamma Correction

To demonstrate loading of GLTF models, the Demo uses an already exported GLTF file from the Demo itself for the same R2 D2 Robot. Just click on the button “Load GLTF File” to load it. You will notice that the loaded model appears darker as compared to OBJ/MTL loaded result. This is so because GLTF models process the model as per their own algorithms needed to store everything in one file. Hence, GLTF models often need more light and something called a “Gamma Correction.” Hence,please switch on those options in the Demo, and then reload to see how it works better. The above options use the component method AddLights and the property UseGammaCorrection.

Changing colors of lights

The Model Demo also shows sample code for changing color of various lights, including the built-in SpotLight and AmbientLight.