Index Topic Contents | |||
Previous Topic: Introduction Next Topic: Using Media Behaviors |
The Basics
This section covers a variety of concepts and techniques useful to many types of DirectAnimation authors: Web site builders, script writers, and application developers. The following topics are discussed in this section:
- Thinking About DirectAnimation
- Media Files Supported by DirectAnimation
- Scripting
- The Statics Class
- Naming Conventions in DirectAnimation
- Viewing DirectAnimation Functions in Visual Basic
- A Simple JScript Example
- A Simple Java Example
- Coordinates in DirectAnimation
- Scripting Timelines Using Duration
- Arrays and Tuples
- URLs and Paths
- Drawing Surface
- Splines
Thinking About DirectAnimation
This section introduces the basic elements of the DirectAnimation model, including media expressions in DirectAnimation, and suggests analogies to number expressions and spreadsheets.
Media Expressions
DirectAnimation can be explained in terms of the familiar concept of expressions on numbers in programming languages (Fortran, C++, Visual Basic, Java, and so on). Such expressions are based on operations that construct new numbers from existing numbers. For example, (5 + 7) * 4 + 3 constructs the number 51.
Before expressions were introduced into programming languages, it took the following tedious steps to evaluate this expression:
Load 5 -> x Load 7 -> y Add x,y -> x Load 4 -> y Mult x,y -> x Load 3 -> y Add x,y -> xDirectAnimation uses an expression-based approach to construct more complex media values based on simpler media values and operations working on these values. For example, the expression
frontImage*rotation + backImageEvaluates to a rotating image overlaying a second image, just like the above expression evaluates to 51.
Just as in number algebra a set of operations and numbers combines to return a result according to certain rules, in DirectAnimation a set of operations on animation and media elements combine to produce interesting interactive, animate and mixed-media content. You can apply many of the concepts of algebra to constructing interesting animation in DirectAnimation.
DirectAnimation has a set of abstract data types, for example, a number behavior (NumberBvr) or a color behavior (ColorBvr). Abstract types are described in terms of the high-level operations they support without exposing implementation or representation details. Since it is typical to have thousands of behaviors in an animation, thinking of behaviors as operations on abstract data types can help make the complexity manageable. Operations create composite behaviors; for example, angle = sin(NumberBvr theta), or redGeo = geo.diffuseColor(ColorBvr red), applies the color constant red to a geometry.
As in algebra, where in an expression such as angle = sin(t* 2*pi/period) t is time, behaviors in DirectAnimation can be time-varying. DirectAnimation generalizes time-varying values beyond numbers. For example, you can construct a time-varying image as follows:
ImageBvr image3 = overlay(image1.transform(rotate(localTime)), image2)This expression sets image3 to be image1 rotating at one radian per second and overlaying image2.
Behaviors Are Retained
Time-varying behaviors in DirectAnimation are retained, in the sense that executing a behavior expression (such as the one in the previous section) constructs a data structure that is retained after the execution concludes. This is unlike traditional number expressions in programming languages where the expression evaluates conclusively into a result at the time of execution. In this respect, DirectAnimation expressions are more like cells in a spreadsheet; they don't execute just once, but are retained and their value changes as their parameters (other behaviors) change.
Using behavior expressions relieves the developer of significant maintenance work. For example, assume you have defined a path behavior (Path2Bvr ) called line and a transformation behavior (Transform2Bvr) called wiggle that is a sinusoidal translation. You can then combine them into a time-varying image behavior (ImageBvr ) called wigglingLine. You can then import an image (perhaps a JPEG from a file) and call it background, and overlay wigglingLine on background. Call this time-varying image myImage.
Now, assume you have imported or synthesized a 3-D cube and assigned it a path to traverse or a rate at which to expand. You can texture the animated cube with myImage and get a cube that is both animated and has an animated texture. Once you have joined the texture to the cube, since this joining is retained, the texturing operation keeps checking the time-varying value of its wiggling line, calculating the result, and applying the new texture to the cube. The programmer constructs the relation between the texture and the cube, and then doesn't need to intervene any further. If, on the other hand, the line is fixed and not wiggling, DirectAnimation is optimized not to calculate texture values over and over and thus saves CPU cycles.
Reactive Behaviors
There are two key concepts in DirectAnimation: continuous behaviors and events. These are combined into reactive behaviors. A reactive behavior varies continuously with time and reacts to specific events by switching to new behaviors. For example, a ball bouncing (moving on its path) in a room is a continuous behavior. The ball colliding with the wall or floor is an event.
For example, say you have imported two geometries (from two .X files, for example) that are 3-D balls, with radii r1 and r2, separated by a time-varying distance d. You can define a collision event as:
Collide = Predicate(leq(d, add(r1, r2))That is, when the distance between the two balls is less than or equal to the sum of their radii, they collide.
This event can be used as follows:
bvr1 = until (initial_behavior, Collide, bounce_behavior)The until operation constructs a behavior which starts as an initial behavior (such as "parabolic path") until the event occurs, then switches to a bounce behavior. The behavior switched to after the event can be constant (the ball stops) or calculated from parameters at the time of the event (a new path calculated from the ball's position and direction of the two balls at the time of the collision). Thus, until creates a new reactive behavior (bvr1) that is the first behavior until the event occurs, and then becomes the second behavior.
Similarly, it is possible to define an event based on the user selecting one of the balls by pointing and clicking:
Grab= andEvent(Pick, leftButtonDown)And used as follows:
bvr2= until(parabolic_path_behavior, Grab, follow_mouse_position_behavior)Or you can make the ball explode on either event as follows:
Explosion = orEvent(Collide, Grab) Explosion_Bvr = until(parabolic_path_behavior, Explosion, flying_ball_fragments_behavior)DirectAnimation supports both arrays and tuples. An array is a homogeneous list of behaviors (behaviors that are all of the same type, such as all colors or all images). A tuple is a heterogeneous list of behaviors (behaviors that can be different, such as a color behavior and an image behavior). Tuples are especially useful for grouping behaviors that all switch at the same event. For example:
Synch_tuple = until(tuple1, event, tuple2)This helps to synchronize the switching of different behaviors at one event.
Interactive Versus Reactive Behaviors
Reactivity is the notion of switching from one behavior to another based on some event. Interactivity is the notion of user input and how it influences the progression of the animation. Events can be based on user input (such as a button press) or they can be synthetic (based on computations, such as the collision event discussed previously). User input can be in the form of an event or it can be in the form of a continuous behavior such as moving the mouse cursor. For example, a user can drag the ball with a mouse to give it continuous motion, or click on the ball and stop it with an event. Both plain behaviors and events can be either interactive or computed (synthetically generated).
Media Graphs
DirectAnimation supports rich operations on media types that result in expressions producing composite media values. These expressions construct retained structures that are called a media graph that operates on time-varying entities. Media graphs are akin to scene graphs in 3-D graphics systems, but they differ in that they are mixed-media based and contain combinations of behaviors, events, and user input. User input (as both continuous behaviors and events) feeds into constructed media graphs, which in turn produce visual and audible media behaviors that get presented through a display and speakers.
Media Files Supported by DirectAnimation
DirectAnimation supports the following media file types:
- 3-D images: .wrl and .x files
- 2-D images: .gif, .png, .jpg, and .bmp files
- Video: .avi, .mpg, .mpeg, .mpv, .mp2, .mpe, .mov, and .qt files
- Audio: .mid and .wav files
DirectAnimation supports all the audio and video file types supported in DirectShow. If the user has a DirectShow filter installed for a particular format, such as DV or Line 21 (for closed captions), then this format will also be supported.
Scripting
The DirectAnimation scripting interfaces make it easy to use DirectAnimation from an HTML environment. The library provides a set of methods for animating multimedia elements such as images, sprites, movies, sound as well as 2-D and 3-D objects. It includes support for animation paths, rotations, and other transformations. A timeline sequencing feature makes it possible to build lifelike animations using simple components as modular building blocks.
The library works in cooperation with the DirectAnimation integrated-media control (DAViewerControl). Library calls are made through a scripting language, such as JScript or VBScript, to construct an animation and play it in the Dynamic HTML compositing space.
Typically, you declare your DAViewerControl object as shown in the following JScript sample. The object's name can be anything. Here it is DAControl. The CLSID must be as shown:
<DIV ID=controlDiv> <OBJECT ID="DAControl" STYLE="position:absolute; left:10; top:10;width:500;height:450" CLASSID="CLSID:B6FFC24C-7E13-11D0-9B47-00C04FC2F51D"> </OBJECT> </DIV> <SCRIPT LANGUAGE="JScript"> <!-- m = DAControl.PixelLibrary; ... //--> </SCRIPT>The variable "m" is shorthand for the DAStatics Library. Every function and property that is in that library needs to be preceded by an "m" so the interpreter knows where to find them. For example:
myImage = m.SolidColorImage(m.Red);In this example, SolidColorImage is a DAStatics function that creates a DAImage object, and Red is a DAStatics property that defines the color red.
Once you have constructed the renderable media type (an image or sound), you tell the DAViewerControl object what to display, as shown in the following JScript code:
DAControl.Image = myImage; DAControl.Sound = mySound;Then tell the object to start the model with the Start subroutine, as shown in the following JScript code:
DAControl.Start();The DAViewerControl has the CLSID B6FFC24C-7E13-11D0-9B47-00C04FC2F51D and is a windowless control, so it can be used with Dynamic HTML, and it can be used over or under other objects on the screen. DirectAnimation also provides the more traditional windowed control (class DAViewerControlWindowed) with the CLSID 69AD90EF-1C20-11D1-8801-00C04FC29D46. If you are working in a traditional environment, such as Visual Basic, it is recommended that you use the windowed control.
The Statics Class
The DAStatics class (in Java, the com.ms.dxmedia.Statics class) collects all the static functions and constants provided by the other classes and makes them available as static methods on the DAStatics (Java Statics class. In scripting languages, this means all the static functions and constants are available through the control object. For example:
<DIV ID=controlDiv> <OBJECT ID="DAControl" STYLE="position:absolute; left:10; top:10;width:500;height:450" CLASSID="CLSID:B6FFC24C-7E13-11D0-9B47-00C04FC2F51D"> </OBJECT> </DIV> <SCRIPT LANGUAGE="JScript"> <!-- m = DAControl.PixelLibrary; ... //--> </SCRIPT>After this declaration, every function, property, and constant that is in the DAStatics library needs to be preceded by an "m" so the interpreter knows where to find them. For example:
myImage = m.SolidColorImage(m.Red);In Java, all of the static methods in the Statics library become available without qualification. For example:
ImageBvr im = solidColorImage(blue);If programmers want to write DirectAnimation code outside of a Model class and not have to qualify their calls to static methods, they can create their own class that extends the DAStatics class. If this is not feasible (because the class already extends another class) then explicit name qualifications are required.
Naming Conventions in DirectAnimation
This section discusses the naming conventions used in the COM API, which are exposed to JScript and VBScript users. In COM and thus in scripting when two similar methods differ only in the type of at least one of their parameters, then these two methods must have different names. This is in contrast to other languages such as Java and C++, which make it possible to use the same method name in such a case. For this reason, in the Scripting Reference you'll find different variations of essentially the same method, with slightly adapted names. The different suffixes that are used are as follows:
Anim Naming Convention
The functions with Anim in the name, such as Point2Anim, are counterparts of the non-Anim versions, such as Point2. The difference is that the Anim versions take time-varying parameters, and produce animated results. Functions with Anim take animated parameters of type DANumber or DAString. Functions without Anim take parameters that are doubles, integers, and regular strings. For example the following two statements are equivalent:
M = DAControl.PixelLibrary; P1 = m.Point2(34, 100); P2 = m.Point2Anim(m.DANumber(34), m.DANumber(100));(Note that DANumber(x) converts the regular number x into a number behavior.)
Since the second form is longer, what is its value? It is necessary if you want to construct a time varying point. For example:
//constructs a number that varies between 34 and 50 in 3 secs. xNum = m.SlowInSlowOut(34, 50, 3, 0); // constructs a point that travels on the Y = 100 line, between the two X values in 3 secs. P2 = m.Point2Anim(xNum, m.DANumber(100));P2 is a time-varying point that can be used to build other time-varying entities. For example, it can be used as a parameter to Translate2Point. Note that in cases where there is no non-Anim version of a certain function then the Anim suffix is omitted even if the function's parameters are time-varying, as is the case with Translate2Point.
Rate Naming Convention
Sometimes to construct time-varying values it is easier to specify the rate of change of the value than to specify the value itself. DirectAnimation provides variations to functions that accept rate-of-change parameters as a convenience. For example:
RotXf = m.Rotate2Rate(Math.PI/3);This code constructs a time varying 2-D rotation of PI/3 per second, and is equivalent to:
RotXf = m.Rotate2Anim(m.Mul(m.LocalTime, m.DANumber(Math.PI/3)));Note that Mul is for multiplying two DANumbers together, and LocalTime is time, which increases by one unit per second.
Degrees Naming Convention
Methods with the Degrees suffix take their angle parameters in degrees as opposed to radians. These are, again, convenience functions that spare the user from doing the conversion explicitly, if the user chooses to specify angle parameters in degrees. For example, consider the following statement with radian parameters:
RotXf = m.Rotate2Rate(Math.PI/3);This can be expressed with degrees as:
RotXf = m.Rotate2RateDegrees(60);Viewing DirectAnimation Functions in Visual Basic
To view the DirectAnimation library functions in Visual Basic, follow these steps:
- Install DirectAnimation.
- In Visual Basic, choose Components from the Project menu. A Components dialog box appears.
- On the Controls tab, check the box next to DirectAnimation Library, and click the OK button. The DAViewerControl will appear as a choice in the Toolbox.
- Click on the control in the Toolbox, then draw the control onto a form.
- Choose Object Browser from the View menu. The object browser appears.
- At the top left of the object browser (where it says All Libraries), choose DirectAnimationCtl from the drop-down list.
- Click a class or interface to display its functions.
- Click a function to display its Visual Basic syntax (at the bottom of the object browser).
A Simple JScript Example
The following code creates a red oval and spins it around. To create this JScript example, follows these steps:
- Declare the DAViewerControl windowless control with an <OBJECT> tag.
You can use any name for the control. You can set the control's position and size on the HTML page by specifying the value of the left position, the value of the top position, and the height and width of the control. You can also specify whether the windowless control appears underneath other images and text on the page, by specifying z-index: -1.
<OBJECT ID="DAControl" STYLE="position:absolute; left:30%; top:100;width:300;height:300;z-index: -1" CLASSID="CLSID:B6FFC24C-7E13-11D0-9B47-00C04FC2F51D"> </OBJECT>- In the scripting section of your HTML file, declare a DAStatics library object (m in the example below) and attach it to either the PixelLibrary or MeterLibrary.
m = DAControl.PixelLibrary;- Access functions and subroutines in the DAStatics library through the object (m in the example below) to create or import your media types (such as images, movies, and sound) and animate them.
fillImg = m.SolidColorImage(m.Red);- Set the media to be displayed as a property of the DAViewerControl object, either the Image property or Sound property.
DAControl.Image = finalImg;- Invoke rendering of the control with Start(). Whatever Image property or Sound property the DAViewerControl object has when started determines what will be rendered.
DAControl.Start()Click the Show button to display the JScript example. To see the code, right-click the title "Simple Sample" and choose View Source from the shortcut menu.
You can add interaction to this sample by changing the code to respond to a user-initiated event. You can make an image red until the left mouse button is clicked, then turn it green with the following statement:
fillImg = m.Until(m.SolidColorImage(m.Red), m.LeftButtonDown, m.SolidColorImage(m.Green));The Until function causes fillImg to be red until the LeftButtonDown event occurs, then turns fillImg green.
A Simple Java Example
The following "Hello, World" example demonstrates some of the basic steps involved in developing a DirectAnimation application. The first step uses DirectAnimation for Java to construct an applet that, when displayed, results in a rendered text string that says "Hello, World." There is no animation and no interaction.
import com.ms.dxmedia.*; public class MyModel extends Model { public void createModel(BvrsToRun blist) { FontStyleBvr fs = defaultFont.family(toBvr("Arial").color(blue).bold(); ImageBvr tx = (toBvr("Hello, World"), fs); setImage(tx); } } public class MyApplet extends DXMApplet { public void init(){ // Always call the superclass's init() first to ensure codeBase is set super.init(); // Now set the model setModel(new MyModel()); } }This DirectAnimation applet simply renders a piece of static text. You can make this example more interesting by adding just a few more lines of code. First, however, you must understand how the initial example works.
The DirectAnimation Model class includes the abstract createModel method. MyModel subclasses Model and implements createModel to build behaviors; this example has a string behavior and an image behavior. The createModel method then calls the setImage method to set the model's image behavior.
The DirectAnimation ImageBvr type is constructed by converting a character string ("Hello, World") into a ImageBvr behavior with the toBvr method. The toBvr method converts the literal string "Hello, World" into an image of the text with the font style specified in the defaultFont method.
Next, MyApplet subclasses the DirectAnimation DXMApplet subclass of the Abstract Windows Toolkit (AWT) Applet class. This initializes its superclass DXMApplet to take an instance of the MyModel class. When the applet is invoked, DirectAnimation builds the model (by invoking createModel) and displays it in the applet.
Adding Animation
A small addition to the previous code causes the text to change color continuously as it is rendered. The MyApplet class doesn't change at all, while the MyModel class is changed to the following:
public class MyModel extends Model { public void createModel(BvrsToRun blist) { ColorBvr col = colorHsl(localTime, toBvr(0.5), toBvr(0.5)); FontStyleBvr fs = defaultFont.family(toBvr("Arial")).color(col).bold(); ImageBvr tx = (toBvr("Hello, World"), fs); setImage(tx); } }One line was added to the createModel method. It defines a color, using the colorHsl method. This method allows you to define a color using the Hue, Saturation, Lightness (HSL) model. The colorHsl method takes 0.5 for its saturation and lightness arguments, but uses the built-in behavior called localTime for the hue. The localTime behavior is a time-varying value of type NumberBvr that increases at the rate of one unit per second. Values of all the defined DirectAnimation types are potentially time-varying and interactive.
Using localTime in a color-producing method such as colorHsl yields a time-varying color. Using this time-varying color as an argument in the font style color(col) method yields a time-varying font color. Attaching the time-varying color value to text that is converted into an image produces a time-varying image. Because setImage now sets a time-varying image, the result of this code is an image that is animated.
Note that the entire applet is as you see it. No other methods are required and, in particular, there is no need for a frame loop, even though the applet is displaying an animation. For programmers who have been using the awt.Graphics package to do animation, this means you do not need to worry about threads, while() loops, or repainting the screen.
Adding Simple Interaction
The next step is to add some simple interactivity. The new version of MyModel, listed below, uses the time-varying color until the left mouse button is pressed. It then changes the color to red.
public class MyModel extends Model { public void createModel(BvrsToRun blist) { ColorBvr col = colorHsl(localTime, toBvr(0.5), toBvr(0.5)); ColorBvr mouseCol = (ColorBvr)until(col, leftButtonDown, red); FontStyleBvr fs = defaultFont.family(toBvr("Arial")).color(mouseCol).bold(); ImageBvr tx = (toBvr("Hello, World"), fs); setImage(tx); } }A single line of code adds the ability to be respond to the mouse:
until(col, leftButtonDown, red);This expression produces a color behavior that is initially col and remains so until the leftButtonDown event occurs. When this happens, col changes to red. There is still no need to provide a frameloop. In addition, there is no need to provide an event detection/response loop (to wait for the leftButtonDown), because this is dealt with explicitly in the implementation of the until method.
As this sample shows, time-varying, interactive behaviors are constructed out of media data types and operations. The DirectAnimation run-time system then takes on the task of animation, event detection, and media presentation.
Coordinates in DirectAnimation
The DirectAnimation API uses continuous temporal and spatial 2-D and 3-D coordinate systems. The basic unit of time is the second. The basic unit of space is the meter. The x-axis is the horizontal axis, increasing to the right. The y-axis is the vertical axis, increasing upward. Three-dimensional coordinates are y-axis up, positive z-axis near, and negative z-axis far.
The following diagram demonstrates these coordinate systems.
DirectAnimation provides several mechanisms for handling these differences. Fundamentally, the DirectAnimation coordinate system is a meter-based system. When PARAM tags are used to specify all or part of the model, the coordinate system will implicitly be that of HTML. When the library mode of the DirectAnimation control is set to pixel mode the coordinate system is converted from the DirectAnimation default to the pixel convention. With these methods, the scripter can construct models in resolution-independent units. For example, in JScript:
m = DAControl.PixelLibrary;- or -
m = DAControl.MeterLibrary;This section discusses the following topics:
- HTML and Pixel Coordinates
- Units
- Working with Pixel Values
- Continuous Coordinate Systems
- Image Coordinate System
- Geometry Coordinate System
- Meter-Based Space
- Pixel-Based Space
- Center-Based Positioning
HTML and Pixel Coordinates
HTML uses device pixels as the standard unit of measure with a left-handed coordinate system with the y-axis down and the origin in the upper left corner. When PARAM tags are used to specify animations the coordinate system is that of HTML. The DirectAnimation client controls use a pixel-coordinate system with the y-axis down and the origin in the center of the window.
DirectAnimation is fundamentally a meter-based coordinate system, which is preferred for resolution independent animation. However, DirectAnimation provides the pixel construction mode as a convenience for users who are familiar with the HTML coordinate system and would like their animation coordinates to match that as closely as possible.
When using the PixelLibrary (as opposed to the MeterLibrary) the 2-D coordinate system is left handed with the positive Y axis going downward, and has a centered origin (not an origin in the upper-left-corner, as in the HTML coordinate system). See the sample in Samples\DA\JScript\Templates\CoordsAndPath.html for a detailed example of the pixel construction mode. Also, compare the PixelMode.html and MeterMode.html samples in Samples\DA\JScript\Exercises. All 2-D coordinate references such as points, paths, and translation factors in this construction mode are interpreted as pixel-valued. Note that this is a construction mode only, so when you extract information back, like extents, you get them in meters, since these are the units in the internal representation. For advanced animations, the meter mode is strongly recommended, especially since the conversion from meter to HTML coordinate space is a single transform.
Units
The DirectAnimation API tries to ensure that one unit is actually 1 meter in physical space, but variables such as monitor curvature and monitor controls that change the display area prevent complete accuracy.
DirectAnimation provides predefined constants that you can use as multipliers to convert to other units, including cm, foot, inch, meter, mm, and pixel.
Working with Pixel Values
Given that pixel size differs from one display to another and even across different settings of the same display device, DirectAnimation provides a built-in number behavior, pixel, which is the dimension of a pixel in meters. The pixel is a scalar because the pixel is a square.
The pixel constant allows an author to coordinate synthetic imagery precisely with imported bitmaps regardless of the display resolution.
Continuous Coordinate Systems
Continuous coordinate systems, such as those used by DirectAnimation, provide some key advantages. They remove problems of device- and resolution-dependence, allow for more portable content, and provide more flexibility to the implementation. However, continuous coordinate systems do not always meet the needs of programmers. For example, in addition to continuous time, DirectAnimation also provides the mechanism for applications to control frame generation through application-generated time ticks. Similarly, in spatial coordinates, it is generally the case that a programmer who imports a GIF or JPEG file wants it displayed at the same resolution at which it was authored and stored. For this reason, DirectAnimation supports pixels.
Image Coordinate System
The image coordinate system is called the image plane. Depending on whether the PixelLibrary or MeterLibrary is used, or if PARAM tags are used, the default unit of measure is pixels or meters, and the coordinate system is in pixel coordinates (origin centered, y down), meter coordinates (origin centered, y up), or HTML coordinates (origin in the upper left, y down).
All image and 2-D geometric primitives live in this same continuous coordinate system. This includes all of the Vector2, Point2, Transform2, Path2, Matte, Text, Montage, and Image values.
On its own, the image plane extends infinitely, with an origin and x- and y-axes. DirectAnimation images are constructed in this abstract coordinate system. However, when it is time to display a DirectAnimation image, a certain section of the infinite plane is mapped on a region of a display device called a viewport, as shown in the following illustration.
The programmer decides what the display region or viewport will be. The mapping from the image plane into the viewport is straightforward. The origin of the image plane is mapped to the center of the viewport, and then the mapping happens in like units of measure. For example, if there is a red point 2 centimeters above the origin in the image plane, this point would map to a red pixel 2 centimeters above the center of the viewport. (Note that windowless controls commonly don't occupy their full viewports.)
Geometry Coordinate System
The geometry coordinate system is a 3-D coordinate system of infinite extent where geometric models are specified and transformed. The default unit of measure is the meter. It has an origin and x-, y-, and z-axes. The coordinate system is a right-handed one, as shown in the following illustration.
The following illustration shows the direction of positive rotation along an axis of rotation (the arrow points in the positive direction).
DirectAnimation geometric models are constructed in this abstract coordinate system. However, you must have a camera to display a model. The camera projects infinite space into an infinite plane, which is the image plane discussed in the Image Coordinate System section. In other words, the 2-D image plane is the 3-D projection plane, because the result of projecting geometry through a camera is an image. The resulting abstract image is amenable to the same operations and rules as other images, including the display through a viewport.
Meter-Based Space
In a meter-based 2-D-composition space, 3-D models are authored to a certain size in meters, which is to be preserved in all renderings, and images are imported and scaled into a predetermined size, also in meters, independent of the pixel resolution. You can determine how much to scale an image by determining the bounding box of the imported image, comparing the desired size to the bounding box, and using that factor to scale the image. This effectively compensates for pixel size variability.
While this technique has the advantage of being independent of the device resolution, you need to scale images before displaying them. It thus requires more processing than simple pixel blitting and is prone to pixel aliasing.
Pixel-Based Space
In a pixel-based composition space, images are imported and displayed in a pixel-to-pixel mapping onto the screen, which is the traditional method in 2-D sprite systems and content (for example, 2-D sprite-based games and Director content). While the result is device-resolution dependent, there are several benefits. One is the large amount of legacy material written in this method. The reuse of this content requires using this pixel-based space.
In addition, because the pixels are mapped pixel-to-pixel, without any transformations, this method tends to be very fast and avoids pixel aliasing. The 3-D parts must be scaled based on the pixel size, so that when they are projected into the image plane they have consistent proportionality and coordination with the 2-D images.
Center-Based Positioning
When DirectAnimation imports or constructs an image, it is centered on the origin in the image plane. Similarly, when an image is created by rendering text (which takes no coordinates as parameters), it also is centered on the origin. The center of a camera's field of view coincides with the origin of the image plane. This means that scenes, when rendered into images, are centered on the origin.
Scripting Timelines Using Duration
A key concept behind DirectAnimation is the idea of "video editing" or "media timelines." Editing a video sequence and moving a sprite (subimage) along an animation path are conceptually very similar. Both scripted animation, such as that used in multimedia applications, and natural media, such as recorded sound and video, are sequences of clips. Each clip has a local timeline. Each can be used in more than one place on the screen (compositing) or in more than one place in time (sequencing). DirectAnimation uses the term behavior to denote these fundamental building blocks of media presentation.
A DirectAnimation behavior is a subsequence of media with its own timeline. You build an animated presentation by sequencing and compositing (overlaying or rendering) the behavior subsequences. DirectAnimation behaviors support a range of media types. For instance, there are image behaviors that treat video, cel animation, sprite (subimage) animation, and animated line graphics uniformly. There is a sound behavior for mixed, parameterized audio. Animated light behaviors illuminate three dimensional scenes.
Timelines are animation fragments of (typically) fixed duration that can be sequenced together to form complex behaviors. Timelines are a flexible mechanism for constructing, manipulating, and running sequences of animation. For example, consider the following JScript code:
startPt = m.Point2(25, 50); endPt = m.Point2(150, 50); myPath = m.Line(startPt, endPt); followPath = m.FollowPath(myPath, 5);The FollowPath method creates a behavior of fixed duration that represents movement along a geometric path (myPath) that lasts five seconds. There are several ways to create timelines. The most general way is to construct an animation fragment by setting a Duration for a behavior. For example, in the following JScript example, colors are given a duration of 5 seconds:
color1 = m.Red.Duration(5); color2 = m.Green.Duration(5); myImage = m.SolidColorImage(m.Sequence(color1, color2));In general, you can think of behaviors as animations (movies, sounds, sprite animations, 3-D animations, and so on) that run forever.
Consider the following JScript sample:
This script draws a red circle that moves in a straight line. It starts at the beginning of the line, waits 1 second, and then starts to move. It goes from the beginning of the line to end in 4 seconds. It repeats these actions 3 times and then stops at the end. To view the source code, right-click anywhere on the title "Sequencing" title and select View Source from the menu that appears. All measurements are in pixels, so the code uses the PixelLibrary. Because the control is windowless, the red circle can pass on top of or underneath the button. It passes underneath the button if you specify z-index: -1 in the <STYLE> tag within the <OBJECT> tag, as shown in this example.
Arrays and Tuples
A common way to construct behaviors is to loop through a sequence of other behaviors over time. Examples include flipping through pre-rendered images or a list of colors. DirectAnimation supports this through the DAArray and Java ArrayBvr types.
The following JScript sample constructs a DAArray object from an array and uses the NthAnim function with a time-varying parameter to cycle through the array. Click on the title "Array Sample" and choose View Source to see the source code:
The following Java code constructs an ArrayBvr out of a Java array, and uses the nth method with a time-varying parameter to cycle through that list.
ColorBvr[] arr = { red, green, blue, yellow, green, cyan, magenta }; ArrayBvr arrBvr = new ArrayBvr(arr); // build an indexer to go from 0 to length - 1, then back to 0, etc. // going at a rate of one unit per second. NumberBvr indexer = mod(localTime, toBvr(arr.length -1)); // Use this to index into the ArrayBvr. ColorBvr cyclingCol = (ColorBvr)arrBvr.nth(indexer);Note that while nth takes a NumberBvr, it uses the greatest integer value less than the number's value to determine the index. The array's index starts at base 0 and any attempt to index beyond its length generates a run-time error.
Tuple behaviors (DATuple and Java TupleBvr) are the same as array behaviors, except that a tuple object can contain behaviors of different types(such as a DAColor and a DAImage), while the behaviors in an array object must all be the same type. Tuple objects are useful for grouping behaviors that all switch at the same event. For example:
SynchTuple = m.Until(tuple1, event, tuple2);This helps to synchronize many different behaviors to one event.
Note that unlike array behaviors, a tuple behavior cannot have an animated index.
URLs and Paths
Paths in DirectAnimation are created by building a URL base, and then adding relative paths to the base. For example:
mediaBase = "..\\..\\..\\..\\media\\"; sndBase = mediaBase + "sound\\"; imgBase = mediaBase + "image\\"; geoBase = mediaBase + "geometry\\"; mySnd = m.ImportSound(sndBase + "clock1.mp2").Sound; myImage = m.ImportImage(imgBase + "bird.gif"); cubeGeo = m.ImportGeometry(geoBase + "cube.x");When you install the DirectX Media SDK, geometry, image, and sound files are installed by default in DXMedia\Media\geometry, DXMedia\Media\image, and DXMedia\Media\sound directories, respectively. Your path should be the relative path to your media files from where your HTML file resides.
Alternatively, you can specify the URL absolutely. For example:
mySnd = m.ImportSound("file://c:/dxmedia/media/sound/clock1.mp2").Sound; myImage = m.ImportImage("file://c:/dxmedia/media/image/bird.gif");In Java, a base URL is set for you automatically. When you build a Java applet, the base URL is set by default to the directory from which your class files are loaded. If you are creating an application instead of an applet, the base URL is set by default to the current working directory. You can also set the base URL explicitly with the setImportBase method, as shown in the following Java code:
try { setImportBase(new URL("file:/c:/dx/dxm/media/image/")); } catch (MalformedURLException exc){ System.out.println("Bad URL - " + exc); }The URL you specify in setImportBase can be any fully-qualified URL. For example:
setImportBase(new URL("http:/www.mycompany.com/MediaLib/"));To build your full URL relative to the URL base, you retrieve the URL base with the getImportBase method, and then complete your path relative to this base. For example, if your applet was built in the directory C:\Dxm\Samples\DA\Java\MyApp, the following code would set the URL mediaBase to C:\Dxm\Media.
URL mediaBase = buildURL(getImportBase(),"../../../Media/");You then use the URL base as shown in the following code:
ImageBvr image1 = importImage(buildURL(mediaBase, "image/apple.gif")); ImageBvr image2 = importImage(buildURL(mediaBase,"../../MyMediaLibrary/MyImages/peach.gif");You can also override the base URL and specify a fully-qualified URL. Note that the URL does not become the default base URL.
URL altURL = buildURL(getImportBase(),"file:/c:/dx/dxm/media/image/); URL anotherURL = buildURL(getImportBase(),"http:/www.mycompany/MediaLib/");You could then import images as show in the following code:
ImageBvr img1 = importImage(buildURL(altURL, "apple.gif")); ImageBvr img2 = importImage(buildURL(anotherURL, "pictures/orange.gif"));You can also import from absolute URLs without building a URL base. For example:
ImageBvr img1 = importImage(buildURL(getImportBase(), "file:/c:/dx/dxm/media/image/apple.gif")); ImageBvr img2 = importImage(buildURL(getImportBase(), "http:/www.mycompany/MediaLib/pictures/orange.gif"));Drawing Surface
The core DirectAnimation API is based on values and expressions. In contrast, the Drawing Surface API provides an alternative style in which methods are used to set a context and then primitives are rendered based on this context. The context can be saved into a stack and restored. The Drawing Surface API is limited to constructing 2-D vector models, so to get to broader features such as sound, images, and 3-D, use the core API.
You can use the Drawing Surface API in conjunction with the core API. After a 2-D vector model is constructed, it can be rendered into an image and then combined with images based on the core API. In the VBScript sample Runners (\Samples\DA\VBScript\Showcase\Runners.html), the runner model is constructed using the Drawing Surface API, while the animation is constructed using the core API. For basic Drawing Surface samples, see Samples\DA\JScript\Templates\BasicDS.html and Samples\DA\VBScript\Templates\BasicDS.html.
The DADrawingSurface class uses a style of drawing that depends on a graphics context. This is in contrast to the other DirectAnimation classes that use a constructive approach. The constructive approach combines primitive data types into a more complex model, in a hierarchical fashion.
The graphics context approach is analogous to a pen plotter, where the pen acts as the mechanical extension of a hand and the plotter acts as a piece of paper. To draw something, the pen is directed to a location on the plotter and then draws the shape. Many people find this approach to be more familiar than hierarchical modeling. For example, to draw the sun in the sky, it may seem more obvious to simply draw a yellow circle exactly where you want it, instead of first drawing a circle, then creating a yellow circle, and then, with a transform, creating yet another yellow circle that is now correctly placed. The difference is in the approach rather than in capabilities.
A DADrawingSurface object maintains a graphics state object for 2-D graphics. This state includes attributes such as line style, fill style, border style, font style, and 2-D transformations. The drawing commands (such as Oval and RoundRect are always interpreted in terms of the current state. See DADrawingSurface in the Scripting Reference for details about the subroutines and functions.
To use a DADrawingSurface functions and subroutines, create a DAViewerControl object in your HTML as usual, then use the DAStatics subroutine NewDrawingSurface to create the DADrawingSurface object, as shown in the following JScript code:
<DIV ID=controlDiv> <OBJECT ID="DAControl" STYLE="position:absolute; left:10; top:10;width:450;height:450" CLASSID="CLSID:B6FFC24C-7E13-11D0-9B47-00C04FC2F51D"> </OBJECT> </DIV> <SCRIPT LANGUAGE="JScript"> m = DAControl.MeterLibrary; ds = m.NewDrawingSurface();Once you have the DADrawingSurface object ds, you can use its functions and subroutines. For example, the following JScript code draws a line between the specified x and y coordinates.
ds.Line(-0.1,.04, 0.01,.04); DAControl.Image = ds.Image; DAControl.Start(); </SCRIPT>Consider the following JScript sample:
This script draws two static lines and a rotating line, as well as text. To view the source code, right-click anywhere on the title "Drawing Surface" title and select View Source from the menu that appears.
You can use the Structured Graphics control with the Drawing Surface interface. For example, the following VBScript code uses the Drawing Surface methods with the Structured Graphics control's drawing surface:
<OBJECT ID=SG1 STYLE="POSITION: absolute; HEIGHT:200;WIDTH:200;TOP:130;LEFT:215;VISIBILITY;VISIBLE; ZINDEX:1" CLASSID="CLSID:369303C2-D7AC-11d0-89D5-00A0C90833E6"> ... </OBJECT> <SCRIPT LANGUAGE=VBSCRIPT> ... Sub renderNew Set Lib = SG1.Library Set DRS = SG1.DrawSurface Call DRS.LineDashStyle(0) Call DRS.FillColor(Lib.green) Call DRS.SecondaryFillColor(Lib.red) Call DRS.GradientExtent(0,0,200,0) Call DRS.GradientRolloffPower(1) Call DRS.FillStyle(9) Call DRS.Rect(-75,-75,100,100) SG1.DrawSurface = DRS End Sub </SCRIPT>The statement SG1.DrawSurface = DRS resets the Structured Graphics control's drawing surface to what's been created in DRS.
Note on using the DirectAnimation Structured Graphics control with the Drawing Surface interface in the Pixel construction mode:
Although the positive y axis goes downward, angles in the arc and pie functions are interpreted as counter-clockwise. For example, a pie shape created by calling PieDegrees with a starting angle of 0 degrees and an ending angle of 90 degrees will be above the x axis (negative y), while a pie created with a starting angle of 0 degrees and an ending angle of -90 degrees will be below the x axis (positive y).
Splines
DirectAnimation supports animation splines. These are effectively animation paths for numbers, 2-D points and vectors, and 3-D points and vectors. The paths can be linear, quadratic, or cubic b-splines, both rational and non-rational. In DirectAnimation, an animation spline is constructed by supplying an array of knots, control points, and, possibly, weights (all of which themselves are behaviors and are potentially time varying). This creates either a DANumber, DAPoint2, DAPoint3, DAVector2, or DAVector3 behavior.
The CubicBSplinePath function is a form of spline that constructs a 2-D cubic b-spline polynomial path (other forms construct numbers, points and vectors). This path, like any other path, can be stroked as a line, filled by any fill style, or used for extracting a motion path with the FollowPath, FollowPathAngle, and FollowPathAngleUpright functions. See the JScript sample AnnotatedLogo.html in Samples\DA\JScript\Templates where this spline is used as both the shape of the logo and as an animation path for HTML text in a DIV tag.
You need a knot vector and a list of control elements to construct a spline. The control elements (numbers, points, or vectors) relate intuitively to the shape of the spline, while the knots don't. If you want to construct your spline in terms of control elements and not in terms of the knot vector, chose a uniform knot vector with standard end conditions (interpolate first and last points). This means the first and last knots are repeated d times where d is the degree of the spline, and intermediate knots are 1 unit apart. For example, the following JScript function (used in the sample CoordsAndPaths.html in Samples\DA\JScript\Templates) takes a list of 2-D control points, generates the uniform knot vector automatically, and constructs and returns a CubicBSplinePath.
function SimpleSpline(pts) { // divide by 2 since 2-D coordinates. numPts = pts.length/2; // We need 2 more knots (since cubic spline) than control points. knts = new Array(numPts + 2); // Set the uniform knots. Note that the knot vector doesn't need // to start from 0, only the relative spacing between knots is significant. for (i=2; i < numPts; i++) knts[i] = i; // first knot must have duplicity 3 (the degree) to interpolate first point knts[0] = knts[1] = knts[2]; // last knot must have duplicity 3 (the degree) to interpolate last point knts[numPts+1] = knts[numPts] = knts[numPts-1]; // finally construct and return the spline path. return(m.cubicBSplinePath(pts, knts)); }In the absence of a visual authoring tool for creating splines, it may be easiest to create them by using a pencil and paper with a square grid. Draw the X and Y axes and draw the desired spline, then place points that follow the general shape of the spline, starting and ending with the same point that needs to be on the spline. You need to pick either the PixelLibrary or the MeterLibrary. If you use pixels, place the spline points only on the grid points and map each square length to 25 pixels.
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.