Go Up to FireMonkey Applications Guide
FireMonkey 3D uses platform-specific libraries, as follows:
- For Windows, the Direct3D library (part of DirectX; provided in the Winapi unit scope)
- For Mac, the OpenGL library (provided in the Macapi unit scope)
FireMonkey provides several kinds of 3D objects:
- Primitive 3D shapes like TCube, TSphere, and TCone.
- TMesh for complex 3D objects.
- 2D objects extruded into 3D, like TText3D. Extruded objects have three sides: the front, with the original 2D shape; the back, a mirror image of that shape; and the shaft of the extrusion between them.
- Flat 2D objects in 3D space, like TImage3D and TTextLayer3D.
Objects are positioned in 3D space with X, Y, and Z coordinates using a TPosition3D. In addition to Height and Width, they also have a Depth. Flat 2D objects in 3D space are arbitrarily thin with a hard-coded Depth of 0.01. 3D objects have 3D rotation and scaling. Position, size, rotation, and scaling are all relative to the object's center point.
As with 2D controls, any 3D control in FireMonkey can be the parent of any other 3D control. A child's position and rotation is relative to its parent. Moving or rotating a parent will re-position its component subtree. TLayout3D may be used as an otherwise featureless parent to organize other objects.
While 2D objects arranged on a 2D surface require a notion of Z-order to determine their layering, objects in 3D space are inherently ordered, so that when seen from a given vantage point, nearer objects occlude farther ones in the same line of sight.
Every view of 3D space is controlled by a camera. The position and orientation (3D rotation) of the camera determines what you see. 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. A scene may have multiple cameras. After assigning a different one to the Camera property, you must call Repaint manually.
The viewable volume is a frustum, with the near plane slightly in front of the camera. Anything between the camera and that front plane is clipped from view. The angle of the field of view is fixed vertically: making the viewport/form taller makes everything bigger, while making it wider shows more to the sides. The units of position and size are relative to the scale of the field of view.
In addition to an object's view (or absence from view) being determined by the camera, an object can also be set to be seen no matter where the camera points, like fixed status indicators in 3D games. This is done by changing the Projection property from the default pjCamera to pjScreen, so that:
- At Position.Z zero:
- XY 0,0 is the upper-left corner, just like with 2D. (3D position still reflects the position of the center of the object, not its upper-left, as with 2D.)
- The Height, Width, and Depth dimensions are equal to pixels, no matter how the field of view is scaled.
- Because the units are rendered as pixels, dimensions of an object using screen projection are much larger than when using camera projection to appear as the same size.
- The object appears slightly behind the front clipping plane of the frustum. Objects using camera projection have a small gap where they can appear in front of screen-projected objects before being clipped by the front plane.
- At Position.Z greater than zero (away from the viewer):
- Rendered size is smaller.
- Shrinking the view pushes the object farther back, making it even smaller.
- Enlarging the view brings the object closer, making it larger.
- At Position.Z less than zero (toward the viewer):
- Rendered size is larger.
- Shrinking the view brings the object closer, making it even larger.
- Bring it too close, either by shrinking the view or setting Position.Z directly, and the object will move past the front plane of the frustum, causing it to disappear.
- Enlarging the view pushes the object farther back, making it smaller.
In the Form Designer, changing an object's Projection recomputes its position so that it does not move, and also adjusts the size.
Viewing an object or scene from any direction, controlled by the user, is a common 3D application. Although you can compute the position and orientation to achieve the proper camera angle, it is easier to create a virtual camera boom:
- Create an invisible object, like a TDummy, in the same location as the object of interest, or the center of the scene.
- Create the TCamera as a child of the object.
- Set its Position the desired distance away on one of the axes.
- If necessary, set its RotationAngle so that the camera points back along the axis to the location. Make sure the camera is not upside-down.
- You can now rotate the camera around the object simply by changing the RotationAngle of the dummy object. The camera maintains the exact distance and automatically points directly toward the center.
- Adding a light as a child of the camera will maintain the distance and orientation of the light as the camera moves.
- Directional light is constant, from a given angle. Light from the sun is a common analog: it is from very far away, so for any localized spot on earth--yards across, not miles -- all items are lit the same. The position of a directional light is irrelevant to its effect. (Its position is relevant if you try to click it in the Form Designer.) What matters is the direction the light points, as defined by its RotationAngle, and the RotationAngle of its parents.
- Point light is like a bare light bulb (with no stem). It radiates in all directions, and falls off with distance. Its RotationAngle has no effect. What matters is its position, which is affected by the position and rotation of its parents.
- Spot light depends on both position and rotation, and falls off with distance.
Flat 2D objects in 3D space neither require, nor are affected by light. They appear as usual with added 3D perspective.
The surface of a FireMonkey 3D object is defined by its material. FireMonkey 3D materials are based on shaders. This allows an unlimited variation of lighting and materials in one application. The list of available materials can be found in Tool Palette under the Materials category. Each FireMonkey 3D object has the MaterialSource property, which links a material source to the current object. To keep a library of materials, use TMaterialBook. To use a single material, source can be linked to as many objects as needed.
To control how an object material appears under the light influence, link it to a TLightMaterialSource:
- Emissive color determines whether a surface emits its own light, or glows. It defaults to null (zero-opacity black): objects normally do not glow, and require light to be seen. By setting a color, surfaces with no light appear with that color. When lit, the emissive color blends with the other colors resulting from light.
- Ambient color is meant to provide a base color to surfaces so that they may be seen. In the real world, light is reflected from many directions onto a surface; but in a 3D scene it would be difficult to define all that light. So Ambient color is activated by any light in the space. (With no lights, it has no effect.) The surface is colored fairly uniformly in that color. With any directional light--which does not have to be pointing at the surface--everything looks flat. With point or spot lights, the color attenuates with distance.
- Diffuse color interacts directly with light, including the angle of incidence. With no light, it has no effect. It is common to set Ambient and Diffuse to the same color.
- Specular color simulates a glossy surface by reflecting incident light at a specific angle, instead of diffusing light in many angles. With no light, Specular has no effect. It defaults to white to reflect the light without altering its color.
Mixing 2D and 3D
3D objects must be placed in a 3D container. A 3D object (like a TCube) will not render if placed directly in a 2D container (like a TForm), but it will be shown in Structure View as a child control. Conversely, 2D objects (like a TButton) will not render if placed directly in a 3D container (like a TForm3D), but also it will be shown in Structure View as a child control. Two classes allow nested mixing of 2D and 3D content:
- TLayer3D is a 3D object that contains 2D content. It is like a rectangular sheet of glass that lives in 3D space.
- TViewport3D is a 2D object that contains 3D content. Like TForm3D, it is a "window" into 3D space.
You may nest these containers. For example, you can have an object hierarchy like:
In addition, a few classes directly host 2D content in 3D:
- TTextLayer3D displays text.
- TImage3D displays bitmap images.
- TVideo3D displays video.
Importing 3D Models
FireMonkey framework offers support to import 3D models. The 3D model can be rendered only in 3D container. To import a 3D model, use TModel3D objects. TModel3D can be found within the Tool Palette. To load an object, use the MeshCollection property of the TModel3D. The supported 3D files are .obj, .dae, and .ase.
The models are imported and displayed with texture. If there is no light on the scene, the texture is not visible. An imported model can be manipulated in a basic way (rotated, moved, scaled and resized) as any other 3D object.
The correct displaying of a loaded model depends on the consistence and correction of the loaded file.
- FireMonkey Application Design
- FireMonkey 3D Application wizard
- Tutorial: Creating a FireMonkey 3D Application
- Tutorial: How to Use Cameras in a FireMonkey 3D Application
- Wizards for Creating FireMonkey Cross-Platform Applications and Components
- FireMonkey Quick Start Guide - Creating a 3D Application
- OpenGL Multicolor Tetrahedron (C++) code example