DirectX Media for Animation Media Types |
![]() Previous |
![]() TOC |
![]() Index |
To simplify the coordinated interplay between 2D and 3D in Direct Animation, both images and geometry live in the same coordinate system. Both the 3D space and the image plane are based on the same unit measure, (the meter) and they share the same origin. Furthermore, the image plane is the projection plane. This means the resulting rendered image is in the image plane, and it behaves identically to images that come from other sources. The image plane has the property that geometry, upon projection, scales up, scales down, or maintains the same size, depending on whether it is in-front of, behind of, or exactly at the image plane, respectively.
The mixed media aspects of Direct Animation facilitate what we call 2D/3D interplay. This means that when content includes both 2D and 3D components that are animated and coordinated in space and time, they form a seamless and coherent animation. There are two forms of this interplay. The first is the use of a 2D-composition space, where 3D parts are rendered into images that get coordinated with other animate images in the image plane. The second is the use of a 3D-composition space, where 2D animations are used as textures on 3D surfaces in a 3D space.
The use of a 2D-composition space involves the use of a fixed camera for rendering the 3D parts into the image plane. That plane can be viewed as a transparent film where 2D images are deposited and that is part of a 3D coordinate system where the 3D models dwell and get rendered into this same plane. There are two choices for an author to approach a 2D-composition space. They are pixel-based or meter-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 2D sprite systems and content (For example, 2D sprite-based games and Director content). While the result is device-resolution dependent, there are several benefits. One is the large amount of legacy content that is authored in this method. This means that, the reuse of this content means using this pixel-based space.
Furthermore, because the pixels are blitted pixel-to-pixel, without any transformations, this method tends to be very fast and avoids pixel aliasing. The 3D parts must be scaled based on the pixel size so that when they are projected into the image plane they present a consistent proportionality and coordination with the 2D images.
As an example, we will relate a 3D spaceship to a cornfield image. Assume we have a rendered geometry image of a spaceship centered at (0,0), and we want it to be aligned with pixel 300,280 of the imported cornfield bitmap. We will also assume that we want the spaceship, once it has landed in the cornfield, to be twice the size of some rock on the side of the field.
This is accomplished in the following manner:
// import the space ship model and the corn field and rock images, and set the camera. GeometryBvr spaceshipGeo = importGeometry("spaceship.wrl"); // centered at origin CameraBvr camera = perspectiveCamera(...); // projection point on Z axis ImageBvr cornfield = importImage("cornfield.gif"); ImageBvr rock = importImage("rock.gif"); // determine the X-extent of the space ship post rendering; // i.e., of it's projection to the image plane. // Notice that the rendering operation in this case doesn't actually take place. Bbox2Bvr spaceshipBbox = spaceshipGeo.render(camera).Bbox2(); NumberBvr shipXExtnet = sub(spaceshipBbox.getMax().getX(), spaceshipBbox.getMin().getX()); // and the X-extent of the rock, which varies with pixel size Bbox2Bvr rockBbox = rock.render(camera).Bbox2(); NumberBvr rockXExtnet = sub(rockBbox.getMax().getX(), rockBbox.getMin().getX()); // determine a scale factor that when applied to the space ship, // it's resultant X-extent is twice that of the rock. NumberBvr normalizeFactor = div(mul(toBvr(2), rockXExtent), shipXExtent); GeometryBvr normalizedSpaceship = spaceshipGeo.scale3(normalizeFactor); // when spaceship is at image plane it's rendering is twice the size of the rock, // the rendering is larger when the ship is closer and smaller when further away. ImageBvr travellingSpaceship = normalizedSpaceship. transform(...). // flying behavior render(camera); // if we want a stationary spaceship at pixel 300, 280 // in the corn field, since DxM centers imported images, // first determine what pixel that is after importation. Bbox2 cornfieldBbox = cornfield.Bbox2(); NumberBvr xPos = sub(mul(toBvr(300), pixel), cornfieldBbox.getMin().getX()); NumberBvr yPos = sub(mul(toBvr(280), pixel), cornfieldBbox.getMin().getY()); // then position the rendering of the space ship at that image. ImageBvr landingSpaceship = normalizedSpaceship.render(camera). transform(translate(xPos, yPos)); // finally we will set the model to the corn field and the two spaceships ImageBvr model = overlay(travellingSpaceship, overlay(landingSpaceship, overlay(rock, cornfield))); setImage(model);
In a meter-based 2D-composition space, the 3D models are authored to a certain size, in meters, which is to be preserved, and images are imported and scaled into a predetermined size, also in meters, which is independent of the pixel resolution,. The image scale can be achieved by determining the bounding box of an image upon importing and scaling the image to match a desired size. This effectively compensates for pixel size variability.
This method has the advantage of being device-resolution independent and the disadvantage of images needing to be scaled before being displayed. It thus requires more processing than simple pixel blitting and is also prone to pixel aliasing.
We will now apply the meter-based approach to the same example of the rocket ship in the cornfield that we used previously. Remember that the reference is that the X-extent of the spacecraft is twice that of the rock.
// import the space ship model and the corn field and rock images, and set the camera. GeometryBvr spaceshipGeo = importGeometry("spaceship.wrl"); // centered at origin CameraBvr camera = perspectiveCamera(...); // projection point on Z axis ImageBvr cornfield = importImage("cornfield.gif"); ImageBvr rock = importImage("rock.gif"); // determine the X-extent of the space ship post rendering; // i.e., of it's projection to the image plane. // Notice that the rendering operation in this case doesn't actually take place. Bbox2Bvr spaceshipBbox = spaceshipGeo.render(camera).Bbox2(); NumberBvr shipXExtnet = spaceshipBbox.getMax().getX() &en; spaceshipBbox.getMin().getX(); // and the X-extent of the rock, which varies with pixel size Bbox2Bvr rockBbox = rock.Bbox2(); NumberBvr rockXExtnet = sub(rockBbox.getMax().getX(), rockBbox.getMin().getX()); // determine a scale factor that when applied to the rock, // it's resultant X-extent is half that of the spaceship. NumberBvr normalizeFactor = div(mul(toBvr(0.5), shipXExtent), rockXExtent); ImageBvr normalizedRock = rock.scale2(normalizeFactor); // all images in the scene should be normalized consistently ImageBvr normalizedCornfield = cornfield.scale2(normalizeFactor); // to center our landing spaceship at the point of pixel 300, 280 // in the original corn field image, we find the position in the // original image and we apply the normalizing scale factor. Bbox2 cornfieldBbox = cornfield.Bbox2(); NumberBvr xPos = mul(normalizeFactor, sub(mul(toBvr(300), pixel), cornfieldBbox.getMin().getX()); NumberBvr yPos = mul(normalizeFactor, sub(mul(toBvr(280), pixel), cornfieldBbox.getMin().getY()); ImageBvr landingSpaceship = spaceship.render(camera). transform(translate(xPos, yPos)); // finally we will set the model to the corn field and the landing spaceship ImageBvr model = overlay(landingSpaceship, overlay(normalizedRock, normalizedCornfield)); setImage(model);
One of the more controversial choices about the Direct Animation coordinate system relates to where imported or constructed images sit on the image plane. For instance, when a bitmap is imported, it is centered about the origin. Most other systems place the image such that the origin is either in the lower-left hand corner, or the upper-left hand corner. Similarly, in Direct Animation, when an image is created from the rendering of text (which has no coordinates associated with it), it also is centered about the origin.
Remember that the center of the field of view of a camera coincides with the origin the image plane. This means that geometry, when rendered into images, are centered about the origin. This is clearly the sensible thing to do for geometry. For other images, we have chosen to be consistent with this.
The rendering of the geometry/camera combination onto an image and coordinating it with other images, is one-half of the relationship between the coordinate systems of image and geometry. The other half involves pasting images back onto geometry, via texture mapping.
The texture method takes an image and a geometry, and returns a geometry textured with that image. Because both images and geometries are such rich data types, this simple texture method is extremely powerful.
In Version 1 of Direct Animation, all geometry is constructed by importing existing, static geometry files. These files usually have 2D texture coordinates associated with vertices, generally ranging from (0,0) to (1,1). When these geometries are texture-mapped with images, the texture coordinates are mapped to the identical image coordinates.
Note that the current implementation does not behave this way. The way it does behave is rather non-modular and implementation-dependent, and is described in the release notes for the ActiveVRML PDC release in April, 1996. This is an area that is being worked on. Thus, texture map coordinates of (0.3, 0.7) in the geometry map directly to the (0.3, 0.7) point on the image that is being texture mapped.
The correspondence between texture coordinate systems and image coordinate systems is quite simple, but it is also quite powerful and flexible. Consider the task of making an image wiggle along the first dimension as a texture on a cube. This can easily be achieved by texture mapping a horizontally wiggling image onto a static cube, as shown in the following example:
ImageBvr wiggleTexture = origTexture.transform(translate(sin(localTime), toBvr(0))); GeoImage newCube = oldCube.texture(wiggleTexture);
If programmers would like to infinitely tile a smaller texture onto a geometry, they can simply create a tiled image using the tile method, and then use that resultant image as a texture. In all of these cases, it is up to the implementation to make the best use of the underlying 3D graphics hardware and software, but from the programmer's perspective, a consistent, very flexible means of using textures is provided.
It is not the goal of this document to describe the picking model in general, but it is relevant to discuss the relationship between picking and coordinate systems. Specifically, we will answer the following question: how does picking work when geometry is embedded into an image, which is textured onto a geometry?
The answer is "the right thing happens." That is, images and geometry, even when embedded, retain their interactive nature. For example, suppose we render a cube that is textured with some interactive image:
ImageBvr im = some interactive image GeometryBvr g = cube.texture(im); CameraBvr camera = perspectiveCamera(...) ImageBvr model = g.render(camera);
If you view model, then pick on cube and into im, im will react in the same way that it would have if we were simply viewing im on its own. We will now elaborate this example:
ImageBvr im = some interactive image; GeometryBvr g1 = some interactive geometry; GeometryBvr g2 = union(cube.texture(im), g1); CameraBvr camera = perspectiveCamera(...); ImageBvr im2 = g2.render(camera); GeometryBvr g3 = sphere.texture(im2); ImageBvr model = g3.render(camera);
Here we have an interactive image textured onto a cube and combined with an interactive geometry. This union is projected onto an image that is then textured onto a sphere. We view the projected sphere model. In this case, picking through either im or g1 still results in pick events, with proper pick data, on im and g1.
In summary, images and geometry, even when embedded, retain their interactive properties.
© 1997 Microsoft Corporation. All rights reserved. Legal Notices.