Skip to content

C++Builder XE5 3D app for iOS - rotating Earth and Mars

In this blog post we’ll take a quick look at 3D iOS application programming using C++Builder XE5 Update 2. This application will contain two rotating planets - Earth and Mars using TSphere, TTextureMaterialSource and TFloatAnimation components. The rotation will be controlled by a TSwitch and the camera Z axis position will be controlled using a TTrackBar.

To start the project I use the "File | New | FireMonkey Mobile Application - C++Builder" menu item and choose the "Blank Application" project template. Since I want my app to always run in landscape mode, the first thing I do (after saving the project) is the set the Project | Options | Application | Orientation to Custom Orientation and Landscape home right.

This simple C++ for iOS project uses an HD form application with two ToolBars (on the top and bottom) for the 2D components (TSwitch, TTrackBar and a few TLabels). The rest of the client area contains a TViewPort3D which allows you to add 3D components onto a HD form. Alternatively you can create a 3D form and put HD components onto the form using a TLayer3D component. If you want to start with a 3D form, the Embarcadero DocWiki has a tutorial "Creating a 2D Interface in a 3D Application (FireMonkey 3D Tutorial)" available at http://docwiki.embarcadero.com/RADStudio/XE5/en/Creating_a_2D_Interface_in_a_3D_Application_(FireMonkey_3D_Tutorial).

Inside the ViewPort3D I use a TDummy container and add two TSphere components and a TCamera to control the scene.

The TDummy container allows me to manipulate all of the contained 3D components at the same time instead of having to write code for each 3D object.

From the DocWiki: "There is always the design camera used in the Form Designer, and by default at run time. It is directly above the negative-Z axis (toward negative-Y), perpendicular to the X-Z plane, angled slightly downward so that position 0,0,0 is in the center of the view. To use a different camera, set the UsingDesignCamera property of the TViewport3D or TForm3D to False, and assign a TCamera to the Camera property."

In my application I set the ViewPort3D’s Camera property to the TCamera (you can have multiple cameras and views just by selecting another camera). Also for the ViewPort3D I set it’s UsingDesignCamera property to false so that the view is controlled by the TCamera.

I set the TCamera’s Target property to the TDummy and set the TCamera’s position X,Y,Z sub-properties to 0,0,0 (so that the camera sits close between the two planets to start).

For each Sphere I added TTextureMaterialSource components and load their Texture properties with bitmaps for the Earth and Mars.

FM’s 3D shapes (Sphere, TCube, TCylinder, TRectangle3D, etc) all have a TMaterialSource property you can set. The choices for MaterialSource property values are: TColorMaterialSource, TLightMaterialSource and TTextureMaterialSource. You can also build up a library of materials using the TMaterialBook class.

Since I loaded the TTextureMaterialSource’s Texture bitmap properties at design time, they are included in the form’s .FMX file (increasing the size of your application). You can also chose to load textures at run time with additional code (use code like TextureMaterialSourceEarth->Texture->LoadFromFile(your bitmap file here) and be sure to include the external bitmap files in your Project | Deployment files list to place the bitmaps in the StartUp\Documents folder). In this example, I wanted to see the planet textures on the TSpheres at design time.

I added a FloatAnimation component component for each TSphere and set the Enabled property to false, PropertyName property to RotationAngle.Y, StartValue property to 0, StopValue property to -360 for Earth (so that it rotates clockwise) and 360 for Mars (so that it rotates counterclockwise), Loop property to true and Duration property to 1 (for Earth) and 2 (for Mars) for the number of seconds (I am not trying to match the rotation period or relative size of each planet in this app, I’ll leave this work to you astronomy/planetary fans).

When the TSwitch is switched, C++ code will enable (or disable) the FloatAnimation components.

void __fastcall TForm5::SwitchRotationSwitch(TObject *Sender)
{
	// If the TSwitch is on - enable the FloatAnimations to
	// start the planets rotating.
	// For TSwitch, the OnSwitch should be used, but I have also
	// associated the OnClick event to this event handler
	// in case the user "clicks" on the switch
	FloatAnimation1->Enabled = SwitchRotation->IsChecked;
	FloatAnimation2->Enabled = SwitchRotation->IsChecked;
}

I use the TTrackBar to move the camera’s Z position between the TrackBar Min value (set to -50) and Max value (set to 50) with a starting value of 0. This will move the camera’s 3D view between the two planets and since the TCamera Target property is set to the TDummy container, you’ll see the planets from the front and the back as the the TrackBar value goes from negative to positive.

From the DocWiki FM 3D document:

  • Position.Z greater than zero (away from the viewer)
  • Position.Z less than zero (toward the viewer)

The C++ code for the TrackBar’s OnChange event handler will change the TCamera’s Position.Z property and also update the TLabel in the top ToolBar to display the current value of the camera’s position.

void __fastcall TForm5::TrackBar1Change(TObject *Sender)
{
	TVarRec vr[] = {TrackBar1->Value};
	ZAxisLabel->Text = Format("Z=%n",vr,1);
	Camera1->Position->Z = TrackBar1->Value;
}

For more information about FM 3D programming, check out the DocWiki "FireMonkey 3D" article at http://docwiki.embarcadero.com/RADStudio/XE5/en/FireMonkey_3D.

That’s a quick look at a simple C++Builder for iOS 3D application (5 lines of user written code) that combines HD and 3D components on the same form. The source code for the project is available on Code Central at http://cc.embarcadero.com/item/29720.

Post a Comment

Your email is never published nor shared. Required fields are marked *

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

Close