Transition3D.java
上传用户:haobig99
上传日期:2022-06-15
资源大小:369k
文件大小:27k
源码类别:

J2ME

开发平台:

Java

  1. /*
  2.  * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
  3.  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4.  *
  5.  * This code is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License version 2 only, as
  7.  * published by the Free Software Foundation.  Sun designates this
  8.  * particular file as subject to the "Classpath" exception as provided
  9.  * by Sun in the LICENSE file that accompanied this code.
  10.  *
  11.  * This code is distributed in the hope that it will be useful, but WITHOUT
  12.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14.  * version 2 for more details (a copy is included in the LICENSE file that
  15.  * accompanied this code).
  16.  *
  17.  * You should have received a copy of the GNU General Public License version
  18.  * 2 along with this work; if not, write to the Free Software Foundation,
  19.  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20.  *
  21.  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22.  * CA 95054 USA or visit www.sun.com if you need additional information or
  23.  * have any questions.
  24.  */
  25. package com.sun.lwuit.animations;
  26. import com.sun.lwuit.Component;
  27. import com.sun.lwuit.Dialog;
  28. import com.sun.lwuit.Display;
  29. import com.sun.lwuit.Graphics;
  30. import com.sun.lwuit.Image;
  31. import com.sun.lwuit.M3G;
  32. import javax.microedition.m3g.AnimationController;
  33. import javax.microedition.m3g.AnimationTrack;
  34. import javax.microedition.m3g.Appearance;
  35. import javax.microedition.m3g.Background;
  36. import javax.microedition.m3g.Camera;
  37. import javax.microedition.m3g.CompositingMode;
  38. import javax.microedition.m3g.Graphics3D;
  39. import javax.microedition.m3g.Group;
  40. import javax.microedition.m3g.Image2D;
  41. import javax.microedition.m3g.IndexBuffer;
  42. import javax.microedition.m3g.KeyframeSequence;
  43. import javax.microedition.m3g.Mesh;
  44. import javax.microedition.m3g.Node;
  45. import javax.microedition.m3g.PolygonMode;
  46. import javax.microedition.m3g.Texture2D;
  47. import javax.microedition.m3g.Transform;
  48. import javax.microedition.m3g.TriangleStripArray;
  49. import javax.microedition.m3g.VertexArray;
  50. import javax.microedition.m3g.VertexBuffer;
  51. import javax.microedition.m3g.World;
  52. /**
  53.  * Transitions utilizing the M3G API for 3D effects, this transition requires
  54.  * M3G (JSR 184) support on the device in order to work properly. Currently
  55.  * none of these transitions work with dialogs or any component type that 
  56.  * is not a form
  57.  *
  58.  * @author Shai Almog
  59.  */
  60. public final class Transition3D extends Transition implements M3G.Callback {
  61.     private static final int FLY_IN = 2;
  62.     private static final int ROTATION = 1;
  63.     private static final int CUBE_ROTATION = 3;
  64.     private static final int STATIC_ROTATION = 4;
  65.     private static final int SWING_IN = 5;
  66.     private static final int VERTICAL_CUBE_ROTATION = 6;
  67.     
  68.     private int transitionType;
  69.     private World world;
  70.     //private int rotation;
  71.     private long startTime;
  72.     private int duration = 1000;
  73.     private static int maxTextureResolution = -1;
  74.     private boolean rotateRight;
  75.     private boolean highQualityMode;
  76.     private boolean firstFinished;
  77.     private int clipX, clipY, clipW, clipH;
  78.     private boolean firstTime = true;
  79.     
  80.     
  81.     private Transition3D(int transitionType) {
  82.         this.transitionType = transitionType;
  83.     }
  84.     
  85.     /**
  86.      * @inheritDoc
  87.      */
  88.     public void cleanup() {
  89.         super.cleanup();
  90.         world = null;
  91.         try {
  92.             Graphics3D.getInstance().setCamera(null, null);
  93.             Graphics3D.getInstance().resetLights();
  94.         } catch(Throwable err) {
  95.         }
  96.         firstTime = true;
  97.     }
  98.     
  99.     private static void initMaxTexture() {
  100.         maxTextureResolution = M3G.getInstance().getMaxTextureDimension();
  101.         // some low resources devices support very high texture values creating out of
  102.         // memory errors, this limits the texture resolution on such low end devices
  103.         if(Display.getInstance().isLightMode()) {
  104.             if(maxTextureResolution > 128) {
  105.                 maxTextureResolution = 128;
  106.             } else {
  107.                 maxTextureResolution = 64;
  108.             }
  109.         }
  110.     }
  111.     
  112.     /**
  113.      * Allows performance/memory sensitive devices to define a maximum size for the 
  114.      * texture thus increasing performance on the expense of quality.
  115.      * @param size
  116.      */
  117.     public static void setMaxTextureDimension(int size) {
  118.         maxTextureResolution = size;
  119.     }
  120.     
  121.     /**
  122.      * Creates a rotation transition from the current form to the next form
  123.      * 
  124.      * @param duration duration in milliseconds of the transition
  125.      * @param rotateRight indicates rotating towards the right side or the left side true == right
  126.      * @return newly created transition object
  127.      */
  128.     public static Transition3D createRotation(int duration, boolean rotateRight) {
  129.         initMaxTexture();
  130.         Transition3D t3d = new Transition3D(ROTATION);
  131.         t3d.duration = duration;
  132.         t3d.rotateRight = rotateRight;
  133.         return t3d;
  134.     }
  135.     /**
  136.      * Creates a rotation transition from the current form to the next dialog, in this rotation only
  137.      * the dialog will rotate and the form will remain static
  138.      * 
  139.      * @param duration duration in milliseconds of the transition
  140.      * @param rotateRight indicates rotating towards the right side or the left side true == right
  141.      * @return newly created transition object
  142.      */
  143.     public static Transition3D createStaticRotation(int duration, boolean rotateRight) {
  144.         initMaxTexture();
  145.         Transition3D t3d = new Transition3D(STATIC_ROTATION);
  146.         t3d.duration = duration;
  147.         t3d.rotateRight = rotateRight;
  148.         return t3d;
  149.     }
  150.     /**
  151.      * Creates a rotation transition from the top to the bottom giving a feeling of Swinging into place
  152.      * 
  153.      * @param duration duration in milliseconds of the transition
  154.      * @return new transtion object
  155.      */
  156.     public static Transition3D createSwingIn(int duration) {
  157.         return createSwingIn(duration, true);
  158.     }
  159.     /**
  160.      * Creates a rotation transition from the top to the bottom giving a feeling of Swinging into place
  161.      * 
  162.      * @param duration duration in milliseconds of the transition
  163.      * @param topDown indicates rotating downwards or upwards
  164.      * @return new transtion object
  165.      */
  166.     public static Transition3D createSwingIn(int duration, boolean topDown) {
  167.         initMaxTexture();
  168.         Transition3D t3d = new Transition3D(SWING_IN);
  169.         t3d.duration = duration;
  170.         t3d.rotateRight = topDown;
  171.         return t3d;
  172.     }
  173.     /**
  174.      * Creates a cube rotation transition from the current form to the next form
  175.      * 
  176.      * @param duration duration in milliseconds of the transition
  177.      * @param rotateRight indicates rotating towards the right side or the left side true == right
  178.      * @return newly created transition object
  179.      */
  180.     public static Transition3D createCube(int duration, boolean rotateRight) {
  181.         initMaxTexture();
  182.         Transition3D t3d = new Transition3D(CUBE_ROTATION);
  183.         t3d.duration = duration;
  184.         t3d.rotateRight = rotateRight;
  185.         return t3d;
  186.     }
  187.     /**
  188.      * Creates a cube rotation transition from the current form to the next form
  189.      * 
  190.      * @param duration duration in milliseconds of the transition
  191.      * @param rotateDown indicates rotating towards the upper side when true
  192.      * @return newly created transition object
  193.      */
  194.     public static Transition3D createVerticalCube(int duration, boolean rotateDown) {
  195.         initMaxTexture();
  196.         Transition3D t3d = new Transition3D(VERTICAL_CUBE_ROTATION);
  197.         t3d.duration = duration;
  198.         t3d.rotateRight = rotateDown;
  199.         return t3d;
  200.     }
  201.     /**
  202.      * Creates a fly in transition object.
  203.      * 
  204.      * @param duration duration in milliseconds of the transition
  205.      * @return newly created transition object
  206.      */
  207.     public static Transition3D createFlyIn(int duration) {
  208.         initMaxTexture();
  209.         Transition3D t3d = new Transition3D(FLY_IN);
  210.         t3d.duration = duration;
  211.         return t3d;
  212.     }
  213.     
  214.     /**
  215.      * @inheritDoc
  216.      */
  217.     public Transition copy(boolean reverse) {
  218.         Transition3D t3d = new Transition3D(transitionType);
  219.         t3d.duration = duration;
  220.         if(reverse) {
  221.             t3d.rotateRight = !rotateRight;
  222.         } else {
  223.             t3d.rotateRight = rotateRight;
  224.         }
  225.         return t3d;
  226.     }
  227.     /**
  228.      * @inheritDoc
  229.      */
  230.     public boolean animate() {
  231.         if(world == null) {
  232.             return false;
  233.         }
  234.         long time = System.currentTimeMillis();
  235.         int current = (int)(time - startTime);
  236.         world.animate(current);
  237.         
  238.         // after the motion finished we need to paint one last time otherwise
  239.         // there will be a "bump" in sliding
  240.         if(firstFinished) {
  241.             return false;
  242.         }
  243.         boolean finished = current >= duration;
  244.         if(finished) {
  245.             if(!firstFinished) {
  246.                 firstFinished = true;
  247.             }
  248.         }
  249.         return true;
  250.     }
  251.     /**
  252.      * @inheritDoc
  253.      */
  254.     public void paint(Graphics g) {
  255.         // prevents painting when the components are too small
  256.         if(world == null) {
  257.             return;
  258.         }
  259.         
  260.         // paint the finished component if the animation completed
  261.         if(firstFinished) {
  262.             getDestination().paintComponent(g);
  263.             return;
  264.         }
  265.         Component c = getSource();
  266.         int titleHeight = 0;
  267.         if(c instanceof Dialog) {
  268.             Dialog dlg = (Dialog)c;
  269.             c = dlg.getContentPane();
  270.             titleHeight = dlg.getTitleComponent().getHeight();
  271.         } else {
  272.             if(getDestination() instanceof Dialog) {
  273.                 Dialog dlg = (Dialog)getDestination();
  274.                 c = dlg.getContentPane();
  275.                 titleHeight = dlg.getTitleComponent().getHeight();
  276.             } else {
  277.                 if(firstTime) {
  278.                     startTime = System.currentTimeMillis();
  279.                     firstTime = false;
  280.                 }
  281.             }
  282.         }
  283.         if(firstTime) {
  284.             startTime = System.currentTimeMillis();
  285.             firstTime = false;
  286.             // paint the whole source form once to make sure we have the proper
  287.             // tinting behavior
  288.             if(getDestination() instanceof Dialog) { 
  289.                 getSource().paintComponent(g);
  290.             } else {
  291.                 getDestination().paintComponent(g);
  292.             }
  293.         }
  294.         clipY = c.getAbsoluteY() - titleHeight;
  295.         clipX = c.getAbsoluteX();
  296.         clipW = c.getWidth();
  297.         clipH = c.getHeight() + titleHeight;
  298.         g.setClip(clipX, clipY, clipW, clipH);
  299.         M3G.getInstance().renderM3G(g, false, Graphics3D.ANTIALIAS, this);
  300.     }
  301.     /**
  302.      * @inheritDoc
  303.      */
  304.     public void initTransition() {
  305.         try {
  306.             Component source = getSource();
  307.             Component dest = getDestination();
  308.             // prevent painting when the components are too small
  309.             if(source == null || dest == null ||
  310.                     source.getWidth() < 4 || source.getHeight() < 4 ||
  311.                     dest.getWidth() < 4 || dest.getHeight() < 4) {
  312.                 return;
  313.             }
  314.             firstFinished = false;
  315.             world = new World();
  316.             Camera camera = new Camera();
  317.             camera.setPerspective(30.0f, 1, 1.0f, 45.0f);
  318.             Transform cameraTransform = new Transform();
  319.             Graphics3D g3d = Graphics3D.getInstance();
  320.             g3d.setCamera(camera, cameraTransform);
  321.             // the whole world is within a single group in the scene graph tree
  322.             Group group = new Group();
  323.             world.addChild(group);
  324.             world.setActiveCamera(camera);
  325.             group.addChild(camera);
  326.             Background background3D = new Background();
  327.             background3D.setColorClearEnable(true);
  328.             background3D.setDepthClearEnable(true);
  329.             background3D.setColor(0xff000000 | source.getStyle().getBgColor());
  330.             world.setBackground(background3D);
  331.             switch(transitionType) {
  332.                 case FLY_IN: {
  333.                     Mesh destMesh = createMesh(dest);
  334.                     group.addChild(destMesh);
  335.                     createFlyIn(destMesh, background3D);
  336.                     break;
  337.                 }
  338.                 case CUBE_ROTATION: {
  339.                     Mesh destMesh = createMesh(dest);
  340.                     createCubeRotation(group, destMesh, false);
  341.                     break;
  342.                 }
  343.                 case VERTICAL_CUBE_ROTATION: {
  344.                     Mesh destMesh = createMesh(dest);
  345.                     createCubeRotation(group, destMesh, true);
  346.                     break;
  347.                 }
  348.                 case ROTATION: {
  349.                     Mesh destMesh = createMesh(dest);
  350.                     group.addChild(destMesh);
  351.                     createRotation(group, destMesh);
  352.                     break;
  353.                 }
  354.                 case SWING_IN:
  355.                 case STATIC_ROTATION: {
  356.                     Mesh destMesh;
  357.                     if(source instanceof Dialog) {
  358.                         destMesh = createMesh(source);
  359.                         source = dest;
  360.                     } else {
  361.                         destMesh = createMesh(dest);
  362.                     }
  363.                     createStaticRotation(group, destMesh, background3D, source, transitionType == SWING_IN);
  364.                     break;
  365.                 }
  366.                 default:
  367.                     throw new IllegalArgumentException("Bad 3D mode : " + transitionType);
  368.             }
  369.             world.animate(0);
  370.             startTime = System.currentTimeMillis();
  371.         } catch(Throwable t) {
  372.             t.printStackTrace();
  373.             cleanup();
  374.         }
  375.     }
  376.     
  377.     private void createFlyIn(Mesh destMesh, Background background3D) {
  378.         background3D.setImage(createImage2D(getSource()));
  379.         KeyframeSequence trans = new KeyframeSequence(10, 3, KeyframeSequence.LINEAR);
  380.         KeyframeSequence alpha = new KeyframeSequence(2, 1, KeyframeSequence.LINEAR);
  381.         alpha.setDuration(duration);
  382.         trans.setDuration(duration);
  383.         
  384.         alpha.setKeyframe(0, 0, new float[] {0.1f});
  385.         alpha.setKeyframe(1, duration, new float[] {1});
  386.         int frac = duration / 10;
  387.         int time = 0;
  388.         
  389.         float position = -31;
  390.         for(int iter = 0 ; iter < 10 ; iter++) {
  391.             float[] pos = new float[] {0, 0, position};
  392.             trans.setKeyframe(iter, time, pos);
  393.             position += 3;
  394.             time += frac;
  395.         }
  396.                 
  397.         AnimationController animation = new AnimationController();
  398.         AnimationTrack track = new AnimationTrack(trans, AnimationTrack.TRANSLATION);
  399.         destMesh.addAnimationTrack(track);
  400.         track.setController(animation);
  401.         track = new AnimationTrack(alpha, AnimationTrack.ALPHA);
  402.         destMesh.addAnimationTrack(track);
  403.         track.setController(animation);
  404.     }
  405.     
  406.     private void createCubeRotation(Group parent, Mesh destMesh, boolean vertical) {
  407.         Group group = new Group();
  408.         parent.addChild(group);
  409.         Mesh sourceMesh = createMesh(getSource());
  410.         group.addChild(destMesh);
  411.         group.addChild(sourceMesh);
  412.         sourceMesh.setTranslation(0f, 0, 1.0f);
  413.         group.translate(0f, 0, -4.7f);
  414.         KeyframeSequence rotation = new KeyframeSequence(3, 4, KeyframeSequence.SPLINE);
  415.         rotation.setDuration(duration);
  416.         
  417.         if(!vertical) {
  418.             if(rotateRight) {
  419.                 destMesh.setOrientation(270, 0, 1, 0);
  420.                 destMesh.setTranslation(-1.0f, 0, 0f);
  421.             } else {
  422.                 destMesh.setOrientation(90, 0, 1, 0);
  423.                 destMesh.setTranslation(1.0f, 0, 0f);
  424.             }
  425.             rotation.setKeyframe(0, 0, getYRoation(0));
  426.             if(rotateRight) {
  427.                 rotation.setKeyframe(1, duration / 2, getYRoation(20));
  428.                 rotation.setKeyframe(2, duration, getYRoation(45));
  429.             } else {
  430.                 rotation.setKeyframe(1, duration / 2, getYRoation(-20));
  431.                 rotation.setKeyframe(2, duration, getYRoation(-45));
  432.             }
  433.         } else {
  434.             if(rotateRight) {
  435.                 destMesh.setOrientation(270, 1, 0, 0);
  436.                 destMesh.setTranslation(0.0f, 1.0f, 0f);
  437.             } else {
  438.                 destMesh.setOrientation(90, 1, 0, 0);
  439.                 destMesh.setTranslation(0.0f, -1.0f, 0f);
  440.             }
  441.             rotation.setKeyframe(0, 0, getXRoationTop(0));
  442.             if(rotateRight) {
  443.                 rotation.setKeyframe(1, duration / 2, getXRoationTop(20));
  444.                 rotation.setKeyframe(2, duration, getXRoationTop(45));
  445.             } else {
  446.                 rotation.setKeyframe(1, duration / 2, getXRoationTop(-20));
  447.                 rotation.setKeyframe(2, duration, getXRoationTop(-45));
  448.             }
  449.         }
  450.                 
  451.         AnimationController animation = new AnimationController();
  452.         AnimationTrack track = new AnimationTrack(rotation, AnimationTrack.ORIENTATION);
  453.         group.addAnimationTrack(track);
  454.         track.setController(animation);
  455.     }
  456.     private void createRotation(Group group, Mesh destMesh) {
  457.         Node sourceMesh = (Node)createMesh(getSource());
  458.         group.addChild(sourceMesh);
  459.         sourceMesh.setTranslation(0, 0, -3.79f);
  460.         destMesh.setTranslation(0, 0, -3.8f);
  461.         
  462.         KeyframeSequence rotationSource = new KeyframeSequence(3, 4, KeyframeSequence.SPLINE);
  463.         KeyframeSequence rotationDest = new KeyframeSequence(3, 4, KeyframeSequence.SPLINE);
  464.         rotationSource.setDuration(duration);
  465.         rotationDest.setDuration(duration);
  466.         
  467.         int half = 45;
  468.         int full = 90;
  469.         // prevent the rotation from staying too long in 90 degrees
  470.         int halfDest = 150;
  471.         int fullDest = 180;
  472.         if(rotateRight) {
  473.             half = -half;
  474.             full = -full;
  475.             halfDest = -halfDest;
  476.             fullDest = -fullDest;
  477.         }
  478.         
  479.         rotationSource.setKeyframe(0, 0, getYRoation(0));
  480.         rotationSource.setKeyframe(1, duration / 4, getYRoation(half));
  481.         rotationSource.setKeyframe(2, duration / 2, getYRoation(full));
  482.         
  483.         rotationDest.setKeyframe(0, 0, getYRoation(full));
  484.         
  485.         rotationDest.setKeyframe(1, duration / 2, getYRoation(halfDest));
  486.         rotationDest.setKeyframe(2, duration, getYRoation(fullDest));
  487.                 
  488.         AnimationController animation = new AnimationController();
  489.         AnimationTrack track = new AnimationTrack(rotationSource, AnimationTrack.ORIENTATION);
  490.         sourceMesh.addAnimationTrack(track);
  491.         track.setController(animation);
  492.         
  493.         track = new AnimationTrack(rotationDest, AnimationTrack.ORIENTATION);
  494.         destMesh.addAnimationTrack(track);
  495.         track.setController(animation);
  496.     }
  497.     private void createStaticRotation(Group group, Mesh destMesh, Background background3D, Component source, boolean swingIn) {
  498.         background3D.setImage(createImage2D(source));
  499.         KeyframeSequence rotationDest;
  500.         
  501.         // prevent the rotation from staying too long in 90 degrees
  502.         int halfDest = 90;
  503.         int fullDest = 180;
  504.         int mid = 135;
  505.                 
  506.         AnimationController animation = new AnimationController();
  507.         Node rotatingNode;
  508.         if(swingIn) {   
  509.             rotationDest = new KeyframeSequence(5, 4, KeyframeSequence.SPLINE);
  510.             rotationDest.setDuration(duration);
  511.             Group rotation = new Group();
  512.             group.addChild(rotation);
  513.             rotation.addChild(destMesh);
  514.             
  515.             if(rotateRight) {
  516.                 rotation.translate(0, 0.8f, -4.0f);
  517.                 destMesh.translate(0, -0.8f, 0);
  518.             } else {
  519.                 rotation.translate(0, -0.8f, -4.0f);
  520.                 destMesh.translate(0, 0.8f, 0);
  521.             }
  522.             int quarter = duration / 4;
  523.             if(source == getSource()) {
  524.                 rotationDest.setKeyframe(0, 0, getXRoationTop(halfDest));        
  525.                 rotationDest.setKeyframe(1, quarter, getXRoationTop(mid));
  526.                 rotationDest.setKeyframe(2, quarter * 2, getXRoationTop(fullDest));
  527.                 rotationDest.setKeyframe(3, quarter * 3, getXRoationTop(fullDest + halfDest / 6));
  528.                 rotationDest.setKeyframe(4, duration, getXRoationTop(fullDest));
  529.             } else {
  530.                 rotationDest.setKeyframe(0, 0, getXRoationTop(fullDest));        
  531.                 rotationDest.setKeyframe(1, quarter, getXRoationTop(fullDest + halfDest / 6));
  532.                 rotationDest.setKeyframe(2, quarter * 2, getXRoationTop(fullDest));        
  533.                 rotationDest.setKeyframe(3, quarter * 3, getXRoationTop(mid));
  534.                 rotationDest.setKeyframe(4, duration, getXRoationTop(halfDest));
  535.             }
  536.             rotatingNode = rotation;
  537.         } else {
  538.             if(rotateRight) {
  539.                 halfDest = -halfDest;
  540.                 fullDest = -fullDest;
  541.                 mid = -mid;
  542.             }
  543.             destMesh.setTranslation(0, 0, -3.8f);        
  544.             rotationDest = new KeyframeSequence(3, 4, KeyframeSequence.SPLINE);
  545.             rotationDest.setDuration(duration); 
  546.             group.addChild(destMesh);
  547.             if(source == getSource()) {
  548.                 rotationDest.setKeyframe(0, 0, getYRoation(halfDest));        
  549.                 rotationDest.setKeyframe(1, duration / 2, getYRoation(mid));
  550.                 rotationDest.setKeyframe(2, duration, getYRoation(fullDest));
  551.             } else {
  552.                 rotationDest.setKeyframe(0, 0, getYRoation(fullDest));        
  553.                 rotationDest.setKeyframe(1, duration / 2, getYRoation(mid));
  554.                 rotationDest.setKeyframe(2, duration, getYRoation(halfDest));
  555.             }
  556.             rotatingNode = destMesh;
  557.         }
  558.         
  559.         AnimationTrack track = new AnimationTrack(rotationDest, AnimationTrack.ORIENTATION);
  560.         rotatingNode.addAnimationTrack(track);
  561.         track.setController(animation);
  562.     }
  563.     
  564.     /**
  565.      * Creates a rotation matrix on the Y axis
  566.      */
  567.     private float[] getYRoation(float angle) {
  568.         angle = (float)Math.toRadians(angle);
  569.         return new float[] {0, (float)Math.sin(angle), 0, (float)Math.cos(angle)};
  570.     }
  571.     
  572.     /**
  573.      * Creates a rotation matrix on the top X axis
  574.      */
  575.     private float[] getXRoationTop(float angle) {
  576.         angle = (float)Math.toRadians(angle);
  577.         return new float[] {(float)Math.sin(angle), 0, 0, (float)Math.cos(angle)};
  578.     }
  579.     private Image2D createImage2D(Component c) {
  580.         int w = c.getWidth();
  581.         int h = c.getHeight();
  582.         Dialog dlg = null;
  583.         if(getSource() instanceof Dialog) {
  584.             dlg = (Dialog)getSource();
  585.             w = dlg.getContentPane().getWidth();
  586.             h = dlg.getContentPane().getHeight() + dlg.getTitleComponent().getHeight();
  587.         } else {
  588.             if(getDestination() instanceof Dialog) {
  589.                 dlg = (Dialog)getDestination();
  590.                 w = dlg.getContentPane().getWidth();
  591.                 h = dlg.getContentPane().getHeight() + dlg.getTitleComponent().getHeight();
  592.             } 
  593.         }
  594.         int textureW;
  595.         int textureH;
  596.         if(highQualityMode) {
  597.             // use the true texture maximum resolution ignoring light mode...
  598.             int max = M3G.getInstance().getMaxTextureDimension();
  599.             textureW = Math.min(M3G.closestHigherPowerOf2(w - 1), max);
  600.             textureH = Math.min(M3G.closestHigherPowerOf2(h - 1), max);
  601.         } else {
  602.             textureW = Math.min(M3G.closestLowerPowerOf2(w + 1), maxTextureResolution);
  603.             textureH = Math.min(M3G.closestLowerPowerOf2(h + 1), maxTextureResolution);
  604.         }
  605.         Image mutable = Image.createImage(w, h);
  606.         Graphics g = mutable.getGraphics();
  607.         if(c instanceof Dialog) {
  608.             c = dlg.getContentPane();
  609.             g.translate(-c.getAbsoluteX(), -c.getAbsoluteY() + dlg.getTitleComponent().getHeight());
  610.             dlg.getContentPane().paintComponent(g, false);
  611.             dlg.getTitleComponent().paintComponent(g, false);
  612.             //g.setClip(c.getAbsoluteX(), c.getAbsoluteY() + dlg.getTitleComponent().getHeight(), mutable.getWidth(), mutable.getHeight());
  613.         } else {
  614.             if(dlg != null) {
  615.                 Component content = dlg.getContentPane();
  616.                 g.translate(-content.getAbsoluteX(), -content.getAbsoluteY() + dlg.getTitleComponent().getHeight());
  617.             } else {
  618.                 g.translate(-c.getAbsoluteX(), -c.getAbsoluteY());
  619.             }
  620.             c.paintComponent(g);
  621.         }
  622.         mutable = mutable.scaled(textureW, textureH);
  623.         return M3G.getInstance().createImage2D(Image2D.RGB, mutable);
  624.     }
  625.     
  626.     private Mesh createMesh(Component c) {
  627.         Texture2D tex = createTexture(createImage2D(c));
  628.         CompositingMode cm = new CompositingMode();
  629.         cm.setBlending(CompositingMode.ALPHA);
  630.         cm.setAlphaWriteEnable(true);
  631.         cm.setDepthTestEnable(true);
  632.         Appearance appearance = new Appearance();
  633.         PolygonMode polyMode = new PolygonMode();
  634.         polyMode.setPerspectiveCorrectionEnable(true);
  635.         appearance.setPolygonMode(polyMode);
  636.         appearance.setCompositingMode(cm);
  637.         appearance.setTexture(0, tex);
  638.             
  639.         VertexBuffer vb = makeGeometry(); 
  640.         int[] indicies = {1,2,0,3};  // one quad 
  641.         int[] stripLens = {4}; 
  642.         IndexBuffer ib = new TriangleStripArray(indicies, stripLens); 
  643.         Mesh m = new Mesh(vb, ib, appearance);
  644.         return m; 
  645.     }
  646.     private VertexBuffer makeGeometry() {
  647.         // create vertices
  648.         short[] verts = { -1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0 };
  649.         VertexArray va = new VertexArray(verts.length / 3, 3, 2);
  650.         va.set(0, verts.length / 3, verts);
  651.         // create texture coordinates
  652.         short[] tcs = { 0, 1, 1, 1, 1, 0, 0, 0 };
  653.         VertexArray texArray = new VertexArray(tcs.length / 2, 2, 2);
  654.         texArray.set(0, tcs.length / 2, tcs);
  655.         VertexBuffer vb = new VertexBuffer();
  656.         vb.setPositions(va, 1.0f, null); // no scale, bias
  657.         vb.setTexCoords(0, texArray, 1.0f, null);
  658.         return vb;
  659.     }
  660.     
  661.     /**
  662.      * Creates a texture making 
  663.      */
  664.     private Texture2D createTexture(Image2D img) {
  665.         Texture2D tex = new Texture2D(img); 
  666.         tex.setFiltering(Texture2D.FILTER_NEAREST, Texture2D.FILTER_NEAREST); 
  667.         tex.setWrapping(Texture2D.WRAP_CLAMP, Texture2D.WRAP_CLAMP); 
  668.         tex.setBlending(Texture2D.FUNC_REPLACE); 
  669.         return tex;
  670.     }
  671.     
  672.     /**
  673.      * @inheritDoc
  674.      */
  675.     public void paintM3G(Graphics3D g) {
  676.         g.render(world);
  677.     }
  678.     /**
  679.      * High quality mode renders the transition using smoother graphics but can
  680.      * take a whole lot more memory per texture and bitmap resulting in a likely
  681.      * out of memory error on high resolution/low memory devices with complex UI
  682.      * elements.
  683.      * 
  684.      * @return whether this is high quality rendering mode
  685.      */
  686.     public boolean isHighQualityMode() {
  687.         return highQualityMode;
  688.     }
  689.     /**
  690.      * High quality mode renders the transition using smoother graphics but can
  691.      * take a whole lot more memory per texture and bitmap resulting in a likely
  692.      * out of memory error on high resolution/low memory devices with complex UI
  693.      * elements.
  694.      * 
  695.      * @param highQualityMode indicates whether this is the high quality mode
  696.      */
  697.     public void setHighQualityMode(boolean highQualityMode) {
  698.         this.highQualityMode = highQualityMode;
  699.     }
  700. }