3D Vector Drawing and Text with Papervision3D: Part 2

Exclusive offer: get 50% off this eBook here
Papervision3D Essentials

Papervision3D Essentials — Save 50%

Create interactive Papervision 3D applications with stunning effects and powerful animations

$26.99    $13.50
by Jeff Winder Paul Tondeur | August 2009 | Open Source

In the previous part of the article by Jeff Winder and Paul Tondeur, we saw how to create a template class for the 3D text examples and add interactivity to 3D vector text and shapes. We also discussed about drawing vector shapes such as lines, circles, and rectangles. In this part, we will see how to draw lines with Lines3D and add interactivity to Lines3D lines.

Drawing lines with Lines3D

Before VectorVision was integrated, Papervision3D already had a Lines3D class for drawing 3D lines. Two differences between drawing lines with VectorShape3D and Lines3D are:

  • Whereas VectorShape3D enables you to easily draw rectangles, circles, and ellipses, Lines3D does not have built-in methods to do such things.
  • Lines3D creates lines with a Vertex3D as the start and end point, resulting in 3D projection of the vertices that make the line. On the other hand, VectorShape3D lets you draw a 2D shape, which you then can rotate in order to achieve a 3D perspective.

Let's take a look at how to create straight as well as curved lines with Lines3D, and how to add interactivity. The following class will serve as a template for the Lines3D examples to come:

package
{
import flash.events.Event;
import org.papervision3d.core.geom.Lines3D;
import org.papervision3d.core.geom.renderables.Line3D;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.materials.special.LineMaterial;
import org.papervision3d.view.BasicView;
public class Lines3DTemplate extends BasicView
{
private var lines:Lines3D;
private var easeOut:Number = 0.6;
private var reachX:Number = 0.5
private var reachY:Number = 0.5
private var reachZ:Number = 0.5;
public function Lines3DTemplate ()
{
super(stage.stageWidth,stage.stageHeight);
stage.frameRate = 40;
init();
startRendering();
}
private function init():void
{
//code to be added
}
override protected function onRenderTick(e:Event=null):void
{
var xDist:Number = mouseX - stage.stageWidth * 0.5;
var yDist:Number = mouseY - stage.stageHeight * 0.5;
camera.x += (xDist - camera.x * reachX) * easeOut;
camera.y += (yDist - camera.y * reachY) * easeOut;
camera.z += (-mouseY * 2 - camera.z ) * reachZ;
super.onRenderTick();
}
}
}

Let's first examine what happens when we draw a line using the Lines3D class.

How drawing with Lines3D works

Each line is defined by a start and an end point, both being 3D vertices. The vertices are converted into 2D space coordinates. The lineTo() method of the Flash drawing API is then used to render the line.

To create a line with the Lines3D class, we need to take these steps in the following order:

  • Create line material with the LineMaterial class. The material defines the look of the line.
  • Create a Lines3D instance, which is a do3D that will be used to store and render the lines.
  • Use the Line3D class to instantiate a line.
  • Add the line to the Lines3D instance with the addLine() method.

Equivalent to how Particle instances need to be added in Particles using theaddParticle() method, we add Line3D instances to a Lines3D instance in order to render them.

Lines3D has the following three methods to add Line3D instances:

  • addLine()
  • ad dNewLine()
  • ad dNewSegmentedLine()

Let's have a look at what they do and create some lines.

Straight lines

All t he following code should be added inside the init() method. First we create line material.

var blueMaterial:LineMaterial = new LineMaterial(0x0000FF);

You can pass two optional parameters as shown in the next table:

 

Parameter

Data type

Default value

Description

1

color

Number

0xFF0000

Defines the color of the line material using a 24 bit hexadecimal color value.

2

alpha

Number

1

Sets the transparency of the material.

Papervision3D Essentials Create interactive Papervision 3D applications with stunning effects and powerful animations
Published: September 2009
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

We passed blue as the color and added no transparency.

Next, we instantiate a Lines3D object that will contain and render the lines to be created. The Lines3D class inherits from DisplayObject3D, so we can add the instance to the scene:

lines = new Lines3D();
scene.addChild(lines);

Each line is defined by two 3D vertices, which refer to the start point and the end point.

var v0:Vertex3D = new Vertex3D(-300,0,0);
var v1:Vertex3D = new Vertex3D(-300,300,0);

Now we create a line by instantiating Line3D.

var blueLine:Line3D = new Line3D(lines,blueMaterial,3,v0,v1);

We passed five parameters to the Line3D constructor, all of them required.

 

 

Parameter

Data type

Default value

Description

1

instance

Lines3D

-

The Lines3D instance that will hold and render this line.

2

material

LineMaterial

-

The material for the line.

3

size

Number

-

The weight (thickness) of the line.

4

vertex0

Vertex3D

-

The start vertex, which is the 3D coordinate where the line starts.

5

vertex1

Vertex3D

-

The end vertex, which is the 3D coordinate where the line ends.

Finally, we add the blue line to the Lines3D instance so that it will be rendered:

lines.addLine(blueLine);

Actually this is quite a lot of code to draw just one line. Let's draw another line, this time using a much shorter, inline notation.

var redLine:Line3D = new
Line3D(lines,new LineMaterial(0xFF0000,1),3,new Vertex3D(0,0,0),
new Vertex3D(-300,0,0))
lines.addLine(redLine);

We have just seen how to draw a straight line. Let's make it curved.

Curved lines

To make a line curved, you add a control vertex using the addControlVertex() method. You can only add one control vertex because the curve is defined by a quadratic Bezier. Let's curve the red line we just created.

redLine.addControlVertex(-150,-300,0);

Just like the 3D vertices that define the start and end point of the line, the control vertex is converted into 2D space and rendered using the Flash drawing API, this time using the curveTo() method. The following screenshot shows both—the straight and the curved line:

3D Vector Drawing and Text with Papervision3D: Part 2

Adding lines with addNewLine()

When you call the addNewLine() method, you don't have to create a Line3D instance before you add a new line:

lines.addNewLine(5,0,0,0,300,0,300);

The material that has been passed to the Lines3D constructor defines the color and the transparency of the line. If no material has been passed, the line will use the default material color 0xFF0000 and the default alpha value of 1. The seven parameters required are:

 

Parameter

Data type

Default value

Description

1

size

Number

-

The weight of the line.

2

x0

Number

-

The line's start x position.

3

y0

Number

-

The line's start y position.

4

z0

Number

-

The line's start z position.

5

x1

Number

-

The line's end x position.

6

y1

Number

-

The line's end y position.

7

z1

Number

-

The line's end z position.

Papervision3D Essentials Create interactive Papervision 3D applications with stunning effects and powerful animations
Published: September 2009
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

The addNewLine() method returns the created Line3D instance, enabling you to create a line first and then modify it.

var line:Line3D = lines.addNewLine(5,0,0,0,300,0,300);
line.size = 2;

Or we can create and modify a line within one line of code, in the following example a curved line:

lines.addNewLine(5,0,0,0,300,0,300).addControlVertex(150,150,150);

Creating segmented lines

Dividing a line in multiple segments can help you when z-fighting takes place between the line and another object. The addNewSegmentedLine() method adds a line that is made of two or more segments:

lines.addNewSegmentedLine(3,8,300,0,300,600,0,0);

The parameters of addNewSegmentedLine() are identical to those in addNewLine(), except that you also need to pass the number of segments.

 

Parameter

Data type

Default value

Description

1

size

Number

-

The weight of the line

2

segments

Number

-

The number of segments that make up the line

3

x0

Number

-

The line's start x position

4

y0

Number

-

The line's start y position

5

z0

Number

-

The line's start z position

6

x1

Number

-

The line's end x position

7

y1

Number

-

The line's end y position

8

z1

Number

-

The line's end z position

The next screenshot shows a line made of 8 segments. Setting the transparency to 1 will show a fluent line, but here the transparency of the material is set to 0.6, resulting in a clear view of the segments:

3D Vector Drawing and Text with Papervision3D: Part 2

The addNewSegmentedLine() method returns an array, which contains the Line3D instances that make up the segmented line and can be manipulated. The following code creates a segmented line and curves the third line in the array:

var segLine:Array = lines.addNewSegmentedLine(3,10,300,0,300,0,0,500);
segLine[3].addControlVertex(-10,-30,0);

Note that when you trace the length of the array, the number it returns is one higher than the number of lines you specify. The array element with index 0 does not refer to a visual line. In this example segLine[3] corresponds with the third line.

As said, working with segmented lines can be helpful in avoiding z-sorting problems. When a non-segmented line cuts through a triangle of another object, the whole line will be sorted in front of or behind the triangle. When using a segmented line, the z-sorting process will take into account only the segment that cuts through the triangle. Take a look at the following screenshots. On the left, a non-segmented line runs through a sphere, on the right, a segmented line was used. Both lines are positioned in such a way that they cut right through the center of the sphere. The black line is not segmented and is sorted behind the sphere. The dotted, white line indicates where it should have run. The segmented line does a much better job, giving the desired illusion of cutting through the sphere. Again, the transparency of the segmented line is set to 0.6 to help demonstrate what's happening here.

3D Vector Drawing and Text with Papervision3D: Part 2

Lines3DExample

Adding interactivity to Lines3D lines

Interactivity can be added through the material instance. Taking Lines3DTemplate as a starting point, we will see an example of lines that are interactive.

All of the following code should be added inside the init() method. First we create a material and make it interactive:

var material:LineMaterial = new LineMaterial(0x000000,0.6);
material.interactive = true;

Don't forget to change the super() call in the constructor to make the viewport interactive as well.

We then define the number of lines and add some variables that we will use to create a circular shape of lines:

var numberOfLines:uint = 80;
var radius:Number = 100;
var angle:Number = (Math.PI*2) / numberOfLines;

Next we add a for loop:

for(var i:uint = 0; i < numberOfLines; i++)
{
var v0:Vertex3D = new Vertex3D(-300,0,0);
var v1:Vertex3D = new Vertex3D(300,0,0);
var lines:Lines3D = new Lines3D();
var line:Line3D = new Line3D(lines,material,3,v0,v1);
lines.addLine(line);
scene.addChild(lines);
lines.x = (Math.cos(i*angle) * radius);
lines.y = -300;
lines.z = Math.sin(i*angle) * radius;
lines.rotationY = (-i*angle) * (180/Math.PI) + 270;
lines.addEventListener(InteractiveScene3DEvent.OBJECT_OVER,
linesOverListener);
}

Inside the for loop we create two 3D vertices at each iteration, v0 and v1, that refer to the start and end point of each line. Then we create a Lines3D instance that will contain and render the line. We instantiate Line3D while passing the Lines3D instance, the material, a line weight of 3 and the start and end points. Next, we add the line to the Lines3D instance, which in turn is added to the scene. The position and rotation of each line are defined by some math, which results in a circular arrangement. Finally, we add an event listener to the Lines3D instance, which will trigger the associated handler method when the mouse hovers a line.

The handler method looks as follows:

private function linesOverListener(e:InteractiveScene3DEvent):void
{
Tweener.addTween(e.displayObject3D,{y:200,time:1,transition:
"easeInOutExpo"});
}

Using Tweener, the line that has been hovered tweens upwards from its currenty position of -300 to a new y position of 200. The following image shows three different states of the example:

3D Vector Drawing and Text with Papervision3D: Part 2

InteractiveLines3DExample

Growing lines example

Although the previous example tweened the position of the lines when they were hovered, the lines themselves were pretty static. Their length and shape stayed the same. The next example shows how to grow a line dynamically. We will create a small sphere and move it around. Out of the sphere a line will grow, which curves depending on how the mouse moves.

We first need to prepare the Lines3DTemplate. Remove all the code in the onRenderTick() method that makes the camera interact with the mouse, but leave the super.onRenderTick(); call. Also remove all the private class properties and put these in their place:

private var lines:Lines3D;
private var sphere:Sphere;
private var lineMaterial:LineMaterial;
private var previousVertex:Vertex3D;

Now the class is ready for our example. Most of the work will be done in the render method, but first add this in the init() method:

sphere = new Sphere(new PhongMaterial(new PointLight3D(),0xFFFFFF,
0x484848,10),100,20,20);
scene.addChild(sphere);

lineMaterial = new LineMaterial(0xFFFFFF);
lines = new Lines3D(lineMaterial);
scene.addChild(lines);

lines.addNewLine(2,0,0,0,0,0,0);
previousVertex = lines.geometry.vertices[1];
camera.target = sphere;

Let's run through the above code. We first instantiate a sphere with Phong material and add it to the scene. The sphere will serve as a guide for the dynamic line. We create a line material and a Lines3D instance, of which the latter is added to the scene. Next, we add a line with a weight of 3 and a start and end 3D vertex. Notice that we give the line a length of 0, because when we publish the application we don't want to see a line from the start. The previousVertex variable will be used in the render method but we initially set it to the coordinates of the second 3D vertex inLines3D instance, which is the end point of the line we just added. Finally, we set the sphere as the target of the camera. Now let's move to the render method.

Inside the render method, we let the sphere rotate depending on the mouse position and we move it forward by 100 units per frame:

sphere.localRotationX = -(mouseX/stage.stageWidth) * 360;
sphere.localRotationY = -(mouseY/stage.stageWidth) * 360;
sphere.moveForward(100);

The next piece of code, still in the render method, takes care of growing the line dynamically:

var new Vertex:Vertex3D = new Vertex3D(sphere.x,sphere.y,sphere.z);
var line:Line3D = new Line3D(lines,lineMaterial,2,previousVertex,
newVertex);
lines.addLine(line);
previousVertex = newVertex;

At each frame, we create a new 3D vertex with the coordinates of the sphere at that moment. Also, we create a new line and add it. Finally we set previousVertex to the new 3D vertex.

So what happens here? In each frame, the start position of the new line is defined by previousVertex, which is set to the new 3D vertex after the new line has been added. The end position of every new line is defined by the position of the sphere, which is constantly moving (and rotating if the user moves the mouse). All this results in creating a dynamically growing line that follows the sphere, as shown in the following images:

3D Vector Drawing and Text with Papervision3D: Part 2

If you don't want to lose sight of the sphere because of its growing distance to the camera, adding the following code to the onRenderTick() method copies the position of the sphere to the camera and moves it backward:

camera.copyPosition(sphere);
camera.moveBackward(4000);

To prevent the line from growing too long, we add the following:

if(lines.lines.length > 500)
{
lines.removeLine(lines.lines[0]);
}

Lines3D has a lines property, which is an array that contains the lines added. If this number exceeds 500, we remove the first line from the array by using the removeLine() method.

GrowingLines3DExample

Summary

We discussed the Lines3D class that also allows you to draw 3D lines. Each line is defined by two 3D vertices, which refer to a start point and an end point. As this class works with 3D vertices, it is possible to set z coordinates, resulting in the illusion of lines with depth. You can also add a control point in order to curve a line. The Lines3D and Line3D classes were already part of Papervision3D before VectorVision was incorporated. In several examples, we have seen how to create lines with these classes, add interactivity to them, and make them grow dynamically.

About the Author :


Jeff Winder

Jeff Winder is an independent Flash developer living and working in Amsterdam, the Netherlands. He discovered Flash and ActionScript in 2003, mainly creating timeline animation, but was soon gripped by non-timeline coding. He has a special interest in new technologies that are related to Flash, especially open-source projects such as WiiFlash, FLARToolKit, and Papervision3D. Jeff acquired an MSc in Social Psychology at the University of Amsterdam. He is also a passionate musician, playing guitar and drums. Since 2006 Jeff has been self-employed and working for leading agencies. URL: http://www.jeffwinder.nl

Paul Tondeur

Paul Tondeur is as an internet entrepreneur who lives and works in Amsterdam, the Netherlands.

He started as a freelance PHP and Flash developer during his study multimedia technology in 2003. After successfully completing his study he was asked to become the CTO of a Dutch online marketing agency in 2004. At this company he developed a strong interest for 3D and got the chance to get professionally involved as the technical lead for serious Second Life projects. Second Life was too limited to fulfill his needs to create accessible interactive multiplayer 3D on the web and this is when he found out about Papervision3D during the early days. Because of his passion for the Flash platform this was love at first sight.

At the beginning of 2009, Paul decided he had to take more advantage of his technical skills as an internet entrepreneur. Currently he helps other companies as a Unity, Papervision3D, Red5 and mobile streaming consultant. Together with a team of people around him, he is also involved in creating a browser based MMO, incorporating the usage of Red5, Unity, Flash and Papervision3D.

URL: www.paultondeur.com

Books From Packt

Flash with Drupal
Blender 3D Architecture, Buildings, and Scenery

ImageMagick Tricks
ImageMagick Tricks

Joomla! 1.5 SEO
Joomla! 1.5 SEO

Drupal 6 Search Engine Optimization
Drupal 6 Search Engine Optimization

Mastering phpMyAdmin 3.1 for Effective MySQL Management
Mastering phpMyAdmin 3.1 for Effective MySQL Management

Drupal Multimedia
Drupal Multimedia

jQuery UI 1.6: The User Interface Library for jQuery
jQuery UI 1.6: The User Interface Library for jQuery

Ext JS 3.0 Cookbook
Ext JS 3.0 Cookbook

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