home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 14 / IOPROG_14.ISO / soft / sdkjava / dxma.exe / DXMA05.cab / samples / da / java / showcase / GeoImage / GeoImage.java next >
Encoding:
Java Source  |  1997-11-13  |  12.3 KB  |  309 lines

  1.  
  2. // 
  3. // <Tutorial Section=1 Title="GeoImage Tutorial Introduction">
  4. //
  5. /** 
  6.   GeoImage imports a list of pictures and corresponding labels.
  7.   It textures a picture on a rectangle while preserving aspect ratio
  8.   (the picture is called the GeoImage). The texturing takes place on both
  9.   sides of the rectangle so that the picture is seen from either side.
  10.   The sample animates the geoimage in 3-D, punctuates when the geoimage is in
  11.   the image plane with an audible tick, uses arrow keys and the space
  12.   bar to cycle through the pictures and corresponding labels, and renders
  13.   the original picture as a bitmap, the animate geoimage, and the label.
  14.  
  15.   The key DirectAnimation points that are demonstrated include: <br>
  16.   - aggregate events using orEvent <br>
  17.   - creating a counter with application event data and the untilNotify method<br>
  18.   - using number behaviors as indexes to arrays of behaviors <br>
  19.   - newUninitbvr and init for looping transform and sound <br>
  20.   - texturing images on rectangles while preserving aspect ratio <br>
  21.   - 2-D/3-D interplay, via the relation of geoimage with picture <br>
  22.   - using sound to punctuate instances in the animation <br>
  23.   - rendering text into images <br>
  24.  
  25.  
  26. **/
  27.  
  28. // </Tutorial>          
  29.  
  30. // <Tutorial Section=7.0 Title="Boiler Plates">
  31. // imports
  32. import java.awt.*;        // use Event and Dimension 
  33. import com.ms.dxmedia.*;  // DirectAnimation classes
  34. import java.net.*;        // building URLs
  35.  
  36. public class GeoImage extends DXMApplet {
  37.   public void init() {
  38.     super.init() ;
  39.     setModel(new GeoImageModel(this));
  40.   }
  41. }
  42.  
  43. class GeoImageModel extends Model { 
  44.  
  45.   // stores the height of the applet viewport in the member variable. 
  46.   private NumberBvr _halfHeightNum;
  47.  
  48.   GeoImageModel(DXMApplet dxma) {
  49.     Dimension dim = dxma.getSize();
  50.     // The base unit of measure for DirectAnimation is the meter.
  51.     // Convert the size into meters by multiplying it with the pixelBvr.
  52.     _halfHeightNum = mul(toBvr(dim.height*0.5),pixelBvr);
  53.   }
  54.   
  55. // </Tutorial>
  56.  
  57.   // return max(x, y)
  58.   public static NumberBvr maxNumBvr(NumberBvr x, NumberBvr y) {
  59.     return (NumberBvr) cond(gt(y, x), y, x);
  60.   }        
  61.  
  62. // <Tutorial Section=7.1>
  63.   
  64.   public void createModel(BvrsToRun blst) {
  65.  
  66. // </Tutorial>  
  67.  
  68. // <Tutorial Section=6.0 Title="Load the Images and Specify the Labels">
  69.  
  70.     // set the URL bases for importing the media
  71.     URL mediaBase = getImportBase();
  72.     URL imgBase = buildURL(mediaBase,"image/");
  73.     URL sndBase = buildURL(mediaBase,"sound/");
  74.     URL geoBase = buildURL(mediaBase,"geometry/");
  75.  
  76.  
  77.     // a [-1, 1] square in X and Y with [0, 1] texture coordinates for
  78.     // both of its faces.
  79.     GeometryBvr square = 
  80.         importGeometry(buildURL(geoBase, "square.x"));
  81.  
  82.     // import a list of images, some of these images could have been .gif images
  83.     ImageBvr pics[] = { 
  84.       importImage(buildURL(imgBase, "phantom.jpg")),
  85.       importImage(buildURL(imgBase, "hiddenBeachSS.jpg")),
  86.       importImage(buildURL(imgBase, "hiddenBeachSG.jpg")),
  87.       importImage(buildURL(imgBase, "jotunheimen1.jpg")),
  88.       importImage(buildURL(imgBase, "redWoodCar.jpg")),
  89.       importImage(buildURL(imgBase, "wenatcheeCascades.jpg")),
  90.       importImage(buildURL(imgBase, "tulipsHol1.jpg")),
  91.       importImage(buildURL(imgBase, "tulipsHol2.jpg")),
  92.       importImage(buildURL(imgBase, "yosemiteCreek.jpg")), 
  93.       importImage(buildURL(imgBase, "kidsUtah.jpg")),
  94.       importImage(buildURL(imgBase, "foliageUtah.jpg"))};
  95.     // construct a corresponding array of behaviors
  96.     ArrayBvr pictures = new ArrayBvr(pics);
  97.  
  98.     // ditto for corresponding labels
  99.     StringBvr lbls[] = {
  100.       toBvr("Phantom Is., Crater Lk., Oregon"),
  101.       toBvr("Hidden Beach, Klamath, California"),
  102.       toBvr("Hidden Beach, Klamath, California"),
  103.       toBvr("Jotenheimen, Norway"),
  104.       toBvr("Redwoods N.P., California"),
  105.       toBvr("Wenatchee, Cascades, Washington"),
  106.       toBvr("Tulip Garden, Holland"),
  107.       toBvr("Tulip Garden, Holland"),
  108.       toBvr("Yosemite, California"),
  109.       toBvr("Centerville, Utah"),
  110.       toBvr("Bountiful, Utah")};
  111.     ArrayBvr lables = new ArrayBvr(lbls);
  112.  
  113.     // Construct a NumberBvr counter object, and use it as an interactive 
  114.     // index to select a picture and a corresponding lable.
  115.     NumberBvr numPics = lables.length();
  116.     index = (NumberBvr) (new Counter(numPics)).getBvr().runOnce();
  117.     ImageBvr picture = (ImageBvr) pictures.nth(index);
  118.     StringBvr lable = (StringBvr) lables.nth(index);
  119. // </Tutorial>
  120.  
  121. // <Tutorial Section=5.0 Title="Texture the Picture while Preserving Aspect Ratio">
  122.  
  123.     // Extract the extent of the picture and scale the square
  124.     // into a rectangle with the same extent, to preserve the
  125.     // picture's aspect ratios upon texturing
  126.     Bbox2Bvr pictureBbox = picture.boundingBox();
  127.     Point2Bvr ll = pictureBbox.getMin();
  128.     Point2Bvr ur = pictureBbox.getMax();
  129.     NumberBvr xUpperRight = ur.getX();
  130.     NumberBvr yUpperRight = ur.getY();
  131.     Transform3Bvr scaleSquare = scale(xUpperRight, yUpperRight, toBvr(1));
  132.     NumberBvr maxHalfExtent = maxNumBvr(xUpperRight, yUpperRight);
  133.  
  134.     // GeoImage has the property that when it lies in the image plane
  135.     // it will have dimensions equal to its bitmap counterpart.
  136.     GeometryBvr geoImage = square.transform(scaleSquare).
  137.     // The picture is normalized before texturing since the
  138.     // square's texture coordinates assume a unit square texture.
  139.       texture(picture.mapToUnitSquare());
  140.  
  141. // </Tutorial>
  142.  
  143. // <Tutorial Section=3.0 Title="The 3-D animation">
  144.     
  145.     // the length of the first segment of the animation in seconds
  146.     NumberBvr period = toBvr(6);
  147.     // time-varying angle, does a complete cycle per period
  148.     NumberBvr aniAngle = mul(localTime, mul(toBvr(2), 
  149.       div(toBvr(Math.PI), period)));
  150.  
  151.     // A translation between front and back Z limits used for 
  152.     // travel of the center of the geometric image.
  153.     // The limits are related to the extent of the picture.
  154.     NumberBvr distOfTravel = mul(toBvr(20), maxHalfExtent); 
  155.     Transform3Bvr trans = translate(toBvr(0), toBvr(0), 
  156.       mul(neg(distOfTravel), sin(aniAngle)));
  157.     // a rotation with rate "aniAngle" around a time varying axis
  158.     Transform3Bvr rot = rotate(vector3(sin(aniAngle), cos(aniAngle), 
  159.       div(sin(aniAngle), toBvr(2))), aniAngle);
  160.         
  161.     // tumbling in 3-D animation, performs a complete cycle in one "period":
  162.     Transform3Bvr rot1 = compose(trans, rot);
  163.  
  164.     // open page animation, opens in one quarter of "period":
  165.     Transform3Bvr rot2 = 
  166.         compose(translate(neg(xUpperRight), toBvr(0), toBvr(0)), 
  167.           compose(rotate(yVector3, neg(aniAngle)),
  168.             translate(xUpperRight, toBvr(0), toBvr(0))));
  169.  
  170.     // close page animation, closes in one quarter of "period":
  171.     Transform3Bvr rot3 = 
  172.         compose(translate(neg(xUpperRight), toBvr(0), toBvr(0)), 
  173.           // the -PI/2 is to pick up from where the page open animation left of
  174.           compose(rotate(yVector3, add(div(neg(toBvr(Math.PI)), toBvr(2)), aniAngle)),
  175.             translate(xUpperRight, toBvr(0), toBvr(0))));
  176.  
  177.     // the cyclic animation of the geoimage:
  178.     //              - tumbling in 3-D in one "period"
  179.     //              - open page in quarter of "period"
  180.     //              - close page in quarter of "period"
  181.     NumberBvr quarterPeriod = div(period, toBvr(4));
  182.     Transform3Bvr loopingTrans = Transform3Bvr.newUninitBvr();
  183.     loopingTrans.init(until(rot1, timer(period), 
  184.       until(rot2, timer(quarterPeriod),
  185.         until(rot3, timer(quarterPeriod), loopingTrans))));       
  186.  
  187.     GeometryBvr loopingGeoImage = geoImage.transform(loopingTrans);
  188. // </Tutorial>
  189.  
  190. // <Tutorial Section=4.0 Title="Sound Punctuation & Rendering the Label">
  191.  
  192.     // Generate a tick everytime the geoimage lies in the image plane.
  193.     // At that point the original picture (bitmap in image plane)
  194.     // coincides with geoimage (a 3-D rendering of a textured rectangle).
  195.     // GeoImage's projection is larger than the picture when closer than the
  196.     // image plane and its projection is smaller when it's further away.
  197.  
  198.     // import the ping sound.
  199.     SoundBvr ping = importSound(buildURL(sndBase, "butin.wav"), null);
  200.  
  201.     // Could have set the looping sound like the transform above;
  202.     // Instead, demonstrate the cycler.
  203.     // alternative:
  204.     //  NumberBvr halfPeriod = div(period, toBvr(2));
  205.     //      SoundBvr loopingSound = SoundBvr.newUninitBvr();
  206.     //  loopingSound.init(until(ping, timer(halfPeriod), loopingSound));
  207.     NumberBvr halfPeriod = div(period, toBvr(2));
  208.     Behavior sounds[] = { ping };
  209.     Cycler cyl = new Cycler(sounds, timer(halfPeriod));
  210.     SoundBvr loopingSound = (SoundBvr)(cyl.getBvr());
  211.  
  212.     // label is yellow, bold, centered horizontally, and 15% above bottom
  213.     Transform2Bvr lablePos = translate(toBvr(0), mul(toBvr(-0.85), _halfHeightNum));
  214.     
  215.         FontStyleBvr fs = defaultFont.color(yellow).bold();
  216.       
  217.     ImageBvr lableImage = stringImage(lable, fs).transform(lablePos);
  218.         
  219. // </Tutorial>
  220.  
  221. // <Tutorial Section=7.2>
  222.  
  223.         // Don't want part of geoimage to be clipped when its center
  224.         // is at distOfTravel, so set the near plane slightly further than that
  225.         // and set the projection point a bit further than the near plane.
  226.     NumberBvr nearDist = add(distOfTravel, mul(toBvr(2.5), maxHalfExtent));
  227.     CameraBvr camera = perspectiveCamera(add(nearDist, 
  228.       mul(maxHalfExtent, toBvr(10))), nearDist);
  229.     // turn on the lights and render geoimage into an image
  230.     GeometryBvr lights = ambientLight; 
  231.     GeometryBvr scene = union(lights, loopingGeoImage);
  232.     ImageBvr renderedGeo = scene.render(camera);
  233.  
  234.     // finally set what's to be displayed on a blue background
  235.     ImageBvr model = overlay(renderedGeo, 
  236.       overlay(lableImage,
  237.         overlay(picture, solidColorImage(blue))));
  238.  
  239.     // the sound behavior to be presented
  240.     setSound(loopingSound);
  241.  
  242.     // the image behavior to be rendered
  243.     setImage(model);
  244.  
  245.   }
  246.   public void cleanup() {
  247.     super.cleanup();
  248.     index = null;
  249.   }
  250.  
  251.   NumberBvr index;
  252. // </Tutorial>
  253. }
  254.  
  255. // <Tutorial Section=2.0 Title="Interacting with geoImage">
  256.  
  257. // This class produces a bidirectional counter that cycles in a given range
  258. // upon button presses. 
  259. class Counter extends Statics implements UntilNotifier {
  260.  
  261.   // constructor for a counter object
  262.   public Counter(NumberBvr limit) {
  263.     _counterLimit = limit;
  264.     // upon a skip event invoke the notifier
  265.     _value = (NumberBvr)untilNotify(_initValue, skip, this);
  266.   }       
  267.  
  268.   public Behavior notify(Object eventData, Behavior previous, BvrsToRun lst) {
  269.     // extract the application data (an integer), into a number behavior
  270.     NumberBvr adjustment = toBvr(((Integer)eventData).intValue());
  271.     // use it as an inc/decrement
  272.     NumberBvr value = add((NumberBvr)previous, adjustment);
  273.     // cycle between 0 and (limit - 1)
  274.     value = (NumberBvr)cond(eq(value, toBvr(-1)), 
  275.       sub(_counterLimit, toBvr(1)),         // if -1, wrap around
  276.         cond(eq(value, _counterLimit), toBvr(0), value)); // if limit, wrap around
  277.     // repeat with the new value
  278.     return untilNotify(value, skip, this);
  279.   }
  280.  
  281.   public NumberBvr getBvr () {
  282.     return _value;
  283.   }
  284.  
  285.   // Key events with corresponding event data.
  286.   // For non-ASCII keys use the Java designation for the key.
  287.   private static final DXMEvent skipForward1 = keyDown(Event.RIGHT).attachData(new Integer(1));
  288.   private static final DXMEvent skipBack1 = keyDown(Event.LEFT).attachData(new Integer(-1));
  289.  
  290.   // For ASCII keys use the ASCII letter between single quotes.
  291.   private static final DXMEvent skipForward2 = keyDown(' ').attachData(new Integer(1));
  292.  
  293.   // There is also a timeout event for automatically switching between pictures
  294.   // if no manual key presses are issued.
  295.   private static final DXMEvent auto = timer(toBvr(8)).attachData(new Integer(1));
  296.  
  297.   // Aggregate the four events above into a single event.
  298.   private static final DXMEvent skip = orEvent(skipForward1, 
  299.                          orEvent(skipBack1,
  300.                            orEvent(skipForward2, auto)));
  301.   // These are aspects of the counter.
  302.   private NumberBvr _counterLimit;
  303.   private NumberBvr _initValue = toBvr(0); // start counting at 0
  304.   private NumberBvr _value;                // current value of counter
  305.  
  306. }
  307. // </Tutorial>
  308.  
  309.