Creating and Warping 3D Text with Away3D 3.6

Exclusive offer: get 50% off this eBook here
Away3D 3.6 Essentials

Away3D 3.6 Essentials — Save 50%

Take Flash to the next dimension by creating detailed, animated, and interactive 3D worlds with Away3D

$29.99    $15.00
by Matthew Casperson | February 2011 | Enterprise Articles Web Graphics & Video

Away3D includes a number of ways to programmatically create 3D objects. A relatively recent addition to Away3D is the ability to create a 3D object from a font, which allows us to easily add 3D text into a scene. This ability is provided by an external library called swfvector.

Away3D also includes the ability to warp a text 3D object by aligning it to a path made up of both straight and curved sections. This article will present a sample application that can warp 3D text, as well as some handy tips on debugging this alignment process. In this article by Matthew Casperson, author of Away3D 3.6 Essentials, we will look at:

  • Embedding fonts into an application
  • Creating a text 3D object
  • Applying materials to the 3D text
  • Giving the 3D text some depth
  • Warping the 3D text along a path

 

Away3D 3.6 Essentials

Away3D 3.6 Essentials

Take Flash to the next dimension by creating detailed, animated, and interactive 3D worlds with Away3D

  • Create stunning 3D environments with highly detailed textures
  • Animate and transform all types of 3D objects, including 3D Text
  • Eliminate the need for expensive hardware with proven Away3D optimization techniques, without compromising on visual appeal
  • Written in a practical and illustrative style, which will appeal to Away3D beginners and Flash developers alike
        Read more about this book      

(For more resources on 3D, see here.)

The external library, swfvector, is contained in the wumedia package. More information about the swfvector library can be found at http://code.google.com/p/swfvector/. This library was not developed as part of the Away3D engine, but has been integrated since version 2.4 and 3.4, to enable Away3D to provide a way to create and display text 3D objects within the scene.

Embedding fonts

Creating a text 3D object in Away3D requires a source SWF file with an embedded font. To accommodate this, we will create a very simple application using the Fonts class below. This class embeds a single true-type font called Vera Sans from the Vera.ttf file.

When compiled, the resulting SWF file can then be referenced by our Away3D application, allowing the embedded font file to be accessed.

When embedding fonts using the Flex 4 SDK, you may need to set the embedAsCFF property to false, like:

[Embed(mimeType="application/x-font", source="Vera.
ttf", fontName="Vera Sans", embedAsCFF=false)]

This is due to the new way fonts can be embedded with the latest versions of the Flex SDK. You can find more information on the embedAsCFF property at http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf6320a-7fea.html.

package
{
import flash.display.Sprite;

public class Fonts extends Sprite
{
[Embed(mimeType="application/x-font", source="Vera.ttf",
fontName="Vera Sans")]
public var VeraSans:Class;
}
}

The font used here is Bitstream Vera, which can be freely distributed, and can be obtained from http://www.gnome.org/fonts/. However, not all fonts can be freely redistributed, so be mindful of the copyright or license restrictions that may be imposed by a particular font.

Displaying text in the scene

Text 3D objects are represented by the TextField3D class, from the away3d.primitives package. Creating a text 3D object requires two steps:

  1. Extracting the fonts that were embedded inside a separate SWF file.
  2. Creating a new TextField3D object.

Let's create an application called FontDemo that creates a 3D textfield and adds it to the scene.

package
{

We import the TextField3D class, making it available within our application.

import away3d.primitives.TextField3D;

The VectorText class will be used to extract the fonts from the embedded SWF file.

import wumedia.vector.VectorText;

public class FontDemo extends Away3DTemplate
{

The Fonts.SWF file was created by compiling the Fonts class above. We want to embed this SWF file as raw data, so we specify the MIME type to be application/octet-stream.

[Embed(source="Fonts.swf", mimeType="application/octet-stream")]
protected var Fonts:Class;

public function FontDemo()
{
super();
}

protected override function initEngine():void
{
super.initEngine();

Before any TextField3D objects can be created we need to extract the fonts from the embedded SWF file. This is done by calling the static extractFonts() function in the VectorText class, and passing a new instance of the embedded SWF file. Because we specified the MIME type of the embedded file to be application/octet-stream, a new instance of the class is created as a ByteArray.

VectorText.extractFont(new Fonts());
}

protected override function initScene():void
{
super.initScene();
this.camera.z = 0;

Here we create the new instance of the TextField3D class. The first parameter is the font name, which corresponds to the font name included in the embedded SWF file. The TextField3D constructor also takes an init object, whose parameters are listed in the next table.

var text:TextField3D = new TextField3D("Vera Sans",
{
text: "Away3D Essentials",
align: VectorText.CENTER,
z: 300
}
);
scene.addChild(text);
}
}
}

The following table shows you the init object parameters accepted by the TextField3D constructor.

3D Text with Away3D 3.6

When the application is run, the scene will contain a single 3D object that has been created to spell out the words "Away3D Essentials" and formatted using the supplied font. At this point, the text 3D object can be transformed and interacted with, just like other 3D object.

3D Text with Away3D 3.6

3D Text materials

You may be aware of applying bitmap materials to the surface of a 3D object according to their UV coordinates. The default UV coordinates defined by a TextField3D object generally do not allow bitmap materials to be applied in a useful manner. However, simple colored materials like WireframeMaterial, WireColorMaterial, and ColorMaterial can be applied to a TextField3D object.

Extruding 3D text

By default, a text 3D object has no depth (although it is visible from both sides). One of the extrusion classes called TextExtrusion can be used to create an additional 3D object that uses the shape of a text 3D object and extends it into a third dimension. When combined, the TextExtrusion and TextField3D objects can be used to create the appearance of a solid block of text. The FontExtrusionDemo class in the following code snippet gives an example of this process:

package
{
import away3d.containers.ObjectContainer3D;
import away3d.extrusions.TextExtrusion;
import away3d.primitives.TextField3D;

import flash.events.Event;

import wumedia.vector.VectorText;

public class FontExtrusionDemo extends Away3DTemplate
{
[Embed(source="Fonts.swf", mimeType="application/octet-stream")]
protected var Fonts:Class;

The TextField3D 3D object and the extrusion 3D object are both added as children of a ObjectContainer3D object, referenced by the container property.

protected var container:ObjectContainer3D;

The text property will reference the TextField3D object used to display the 3D text.

protected var text:TextField3D;

The extrusion property will reference the TextExtrusion object used to give the 3D text some depth.

protected var extrusion:TextExtrusion;

public function FontExtrusionDemo()
{
super();
}

protected override function initEngine():void
{
super.initEngine();
this.camera.z = 0;
VectorText.extractFont(new Fonts());
}

protected override function initScene():void
{
super.initScene();
text = new TextField3D("Vera Sans",
{
text: "Away3D Essentials",
align: VectorText.CENTER
}
);

The TextExtrusion constructor takes a reference to the TextField3D object (or any other Mesh object). It also accepts an init object, which we have used to specify the depth of the 3D text, and to make both sides of the extruded mesh visible.

extrusion = new TextExtrusion(text,
{
depth: 10,
bothsides:true
}
);

The ObjectContainer3D object is created, supplying the TextField3D and TextExtrusion 3D objects that were created above as children. The initial position of the ObjectContainer3D object is set to 300 units down the positive end of the Z-axis.

container = new ObjectContainer3D(text, extrusion,
{
z: 300
}
);

The container is then added as a child of the scene.

scene.addChild(container);
}

protected override function onEnterFrame(event:Event):void
{
super.onEnterFrame(event);

The container is slowly rotated around its Y-axis by modifying the rotationY property in every frame. In previous examples, we have simply incremented the rotation property, without any regard for when the value became larger than 360 degrees. After all, rotating a 3D object by 180 or 540 degrees has the same overall effect. But in this case, we do want to keep the value of the rotationY property between 0 and 360 so we can easily test to see if the rotation is within a given range. To do this, we use the mod (%) operator.

container.rotationY =
(container.rotationY + 1) % 360;

Z-sorting issues can rise due to the fact that the TextExtrusion and TextField3D objects are so closely aligned. This issue results in parts of the TextField3D or TextExturude 3D objects showing through where it is obvious that they should be hidden.

To solve this problem, we can use the procedure to force the sorting order of 3D objects. Here we are assigning a positive value to the TextField3D screenZOffset property to force it to be drawn behind the TextExturude object, when the container has been rotated between 90 and 270 degrees around the Y-axis. When the container is rotated like this, the TextField3D object is at the back of the scene. Otherwise, the TextField3D is drawn in front by assigning a negative value to the screenZOffset property.

if (container.rotationY > 90 &&
container.rotationY < 270)
text.screenZOffset = 10;
else
text.screenZOffset = -10;
}
}
}

The result of the FontExtrusionDemo application is shown in the following image:

3D Text with Away3D 3.6

Away3D 3.6 Essentials Take Flash to the next dimension by creating detailed, animated, and interactive 3D worlds with Away3D
Published: January 2011
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:
        Read more about this book      

(For more resources on 3D, see here.)

Warping 3D text

Away3D can not only create text 3D objects, it can also warp them by aligning them to arbitrary paths made up of straight lines or curves. This can be used to create some interesting effects, like wrapping text around another 3D object. The following TextWarpingDemo class demonstrates how to align a 3D text object to a wave-like curve, a path made up of two straight lines, and a simple, single curve.

package
{

The Path and PathCommand classes are used to define the path that the text will align itself to.

import away3d.core.geom.Path;
import away3d.core.geom.PathCommand;
import away3d.materials.ColorMaterial;

The PathAlignModifier class is responsible for transforming a 3D object to align it to a given path.

import away3d.modifiers.PathAlignModifier;
import away3d.primitives.TextField3D;
import flash.geom.Vector3D;
import flash.events.KeyboardEvent;

import wumedia.vector.VectorText;

public class TextWarpingDemo extends Away3DTemplate
{
[Embed(source="Fonts.swf", mimeType="application/octet-stream")]
protected var Fonts:Class;
protected var text:TextField3D;

public function TextWarpingDemo()
{
super();
}

protected override function initEngine():void
{
super.initEngine();
VectorText.extractFont(new Fonts());
}

protected override function initScene():void
{
super.initScene();
this.camera.z = 0;
followLine();
}

protected override function initListeners():void
{
super.initListeners();
stage.addEventListener(
KeyboardEvent.KEY_UP,
onKeyUp
);
}

protected function onKeyUp(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case 49: // 1
followContinuousCurve();
break;
case 50: // 2
followLine();
break;
case 51: // 3
followCurve();
break;
}
}

The setupText() function will remove an existing text 3D object (if one exists) and recreate it each time we align it to a new path when the followContinuousCurve(), followLine(), and followCurve() functions are called.

protected function setupText():void
{
if (text != null)
{
scene.removeChild(text);
}

You will notice that we have added a few extra spaces in the string we want to display as a 3D object. This is simply to allow the text to align nicely around the right angle we will add in the straight line path created in the followLine() function.

text = new TextField3D("Vera Sans",
{
text: "Away3D Essentials",
size: 15,
material: new ColorMaterial(0)
}
);
scene.addChild(text);
}

The next three functions are used to align the 3D text object to various paths. The followContinuousCurve() function will create a wave-like path to align the text 3D object.

protected function followContinuousCurve():void
{

We call the setupText() function to create our text 3D object.

setupText();

Next, we create a new Path object. It is this object that will contain the points that define the path that our text 3D object will align itself to.

var path:Path = new Path();

Here we have used the continousCurve() function to define a curve with four points, supplied as an array of Vector3D objects. We have defined a curve that starts at (-75, -50, 300), moves up towards (-25, 50, 300), then moves down towards (25, -50, 300), and finally moves towards the last point at (75, 0, 300).

path.continuousCurve(
[
new Vector3D(-100, -50, 300),
new Vector3D(-25, 50, 300),
new Vector3D(25, -50, 300),
new Vector3D(100, 0, 300)
]
);

This creates a path that looks like the following image:

3D Text with Away3D 3.6

Due to the way the curve is calculated, it starts half way in between the first and second points and finishes half way between the last and the second last points. You can confirm this for yourself by adding the following code after the call to the continuousCurve() function:

scene.addChild(new Sphere({x: -75, y: -
50, z: 300, radius: 1, material: new
ColorMaterial(0)}));
scene.addChild(new Sphere({x: -25, y:
50, z: 300, radius: 1, material: new
ColorMaterial(0)}));
scene.addChild(new Sphere({x: 25, y: -
50, z: 300, radius: 1, material: new
ColorMaterial(0)}));
scene.addChild(new Sphere({x: 75, y:
0, z: 300, radius: 1, material: new
ColorMaterial(0)}));
path.debugPath(scene);
path.showAnchors = false;

The sphere 3D objects are positioned in the scene using the same locations as the points we supplied to the continuousCurve() function. Calling the debugPath() function will then create a PathDebug object, which will visually display the path. You will see that the start and end points of the curve lie inbetween the points we supplied to the continuousCurve() function.

We have also set the showAnchors property to false. When set to true (which is the default) the PathDebug object will add a number of sphere 3D objects to show the points that make up the path, much like we have just done manually. However, these spheres have a radius of 50 units, which would unfortunately completely fill up a scene like this. To work around this, you can modify the PathDebug class file, located in the away3d.core.geom package, to change the size of these debug spheres.

The first line of the addAnchor() function looks like this (it is line 72 of the PathDebug.as file):

var sphere:Sphere = new Sphere({material:mat,
radius:50, segmentsH:2, segmentsW:2 });

Simply change the radius init object parameter to something like 5 instead of 50.

We create a new PathAlignModifier object, which will be used to modify our text 3D object so it is aligned to our path. The constructor takes the 3D object that is to be modified, and the path that it will be aligned to.

var aligner:PathAlignModifier =
new PathAlignModifier(text, path);

The execute() function will then make the required changes to the text 3D object.

aligner.execute();
}

The followLine() function is used to align the text 3D object along a path made up of a number of straight lines.

protected function followLine():void
{
setupText();
var path:Path = new Path();

Above, we used the continuousCurve() function from the Path class to create our path. Creating a path with straight lines is a little different. For this, we add a number of PathCommands objects to the array property of the Path class.

The first parameter we supply to the PathCommand constructor is the type of command that we are defining. Since we are defining a straight line, we use the PathCommand.LINE constant.

The second parameter is the starting point of the line.

The third parameter is a control point. This is used when defining a curve, but has no relevance when defining a straight line, so we leave it as null.

The fourth parameter is the end point of the line.

We push() two new PathCommand objects on to the array property of the Path class with the following code snippet:

path.array.push(
new PathCommand(
PathCommand.LINE,
new Vector3D(-75, -35, 300),
null,
new Vector3D(-75, 35, 300)
)
);
path.array.push(
new PathCommand(
PathCommand.LINE,
new Vector3D(-75, 35, 300),
null,
new Vector3D(75, 35, 300)
)
);

This will define a path that looks like the following image:

3D Text with Away3D 3.6

Even though it makes no sense to have a modifier point when defining a straight line, you will find that the PathDebug class expects the modifier points not to be null. If you were to call the debugPath() function on the Path object with the straight line path we have defined above, you would see an error because the PathDebug object tries to read a null modifier point object. The easiest way to visually debug a straight line path is to use either the start or end point as a modifier point. In the following code, we have defined the same path as we did previously, with the exception that the start and modifier points are the same:

path.array.push(
new PathCommand(
PathCommand.LINE,
new Vector3D(-75, -35, 300),
new Vector3D(-75, -35, 300),
new Vector3D(-75, 35, 300)
)
);
path.array.push(
new PathCommand(
PathCommand.LINE,
new Vector3D(-75, 35, 300),
new Vector3D(-75, 35, 300),
new Vector3D(75, 35, 300)
)
);

Again we create a new PathAlignModifier object, supplying the text 3D object and the Path that it should be aligned to, and then call the execute() function to make the changes.

var aligner:PathAlignModifier =
new PathAlignModifier(text, path);
aligner.execute();
}

The followCurve() function will create a single curve to align the text 3D object.

protected function followCurve():void
{
setupText();

var path:Path = new Path();

Just like with the straight line path we created above, the curve is defined by adding a PathCommand object to the array property of the Path class. We specify the type of the PathCommand using the PathCommand.CURVE constant, and then define the curve using a start, modifier, and end point.

path.array.push(
new PathCommand(
PathCommand.CURVE,
new Vector3D(-75, -45, 300),
new Vector3D(0, 50, 300),
new Vector3D(75, 0, 300)
)
);

This will define a curve that looks the like the following image:

3D Text with Away3D 3.6

Again, we create a new PathAlignModifier object, and call it's execute() function.

var aligner:PathAlignModifier =
new PathAlignModifier(text, path);
aligner.execute();
}
}
}

When the application is run you can press the 1, 2, and 3 keys on the keyboard to see the results of warping a text 3D object along the three different types of paths.

Summary

It is possible in Away3D to create text 3D objects and then manipulate them in a variety of ways. This chapter covered how to embed a true-type font file in a SWF that could then be used by the swfvector library. We then looked at a simple application that created a flat text 3D object within the scene.

These text 3D objects can be warped in a variety of interesting ways by aligning them to a path. A sample application was presented that aligned a text 3D object to a variety of paths made with both curves and straight lines.

We also saw how to give the 3D text object some depth with one of the many extrusion classes available in Away3D.


Further resources on this subject:


Away3D 3.6 Essentials Take Flash to the next dimension by creating detailed, animated, and interactive 3D worlds with Away3D
Published: January 2011
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

About the Author :


Matthew Casperson

Matthew Casperson has worked in IT for nearly a decade in a variety of roles including development and support, and in his spare time loves nothing more than to experiment with the latest web and multimedia technologies. Many of these experiments can be found on Matthews personal website at http://goo.gl/2Hgr.

Away3D Essentials is Matthews first book, but hopefully won't be the last!

Books From Packt


Away3D 3.6 Cookbook
Away3D 3.6 Cookbook

OGRE 3D 1.7 Beginner's Guide
OGRE 3D 1.7 Beginner's Guide

3D Graphics with XNA Game Studio 4.0
3D Graphics with XNA Game Studio 4.0

Panda3D 1.6 Game Engine Beginner's Guide
Panda3D 1.6 Game Engine Beginner's Guide

Unity 3D Game Development by Example Beginner's Guide
Unity 3D Game Development by Example Beginner's Guide

Papervision3D Essentials
Papervision3D Essentials

Blender 2.5 Materials and Textures Cookbook
Blender 2.5 Materials and Textures Cookbook

OpenSceneGraph 3.0: Beginner's Guide
OpenSceneGraph 3.0: Beginner's Guide


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
w
U
V
w
t
Y
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software