×
Namespaces

Variants
Actions
(Difference between revisions)

Using M3G Animation in Java ME

From Nokia Developer Wiki
Jump to: navigation, search
kiran10182 (Talk | contribs)
m
IlGolub (Talk | contribs)
Line 29: Line 29:
 
<code java>
 
<code java>
 
import java.io.IOException;
 
import java.io.IOException;
 
+
 
import java.util.Timer;
 
import java.util.Timer;
 
import java.util.TimerTask;
 
import java.util.TimerTask;
 
+
import javax.microedition.lcdui.Alert;
+
 
import javax.microedition.lcdui.Canvas;
 
import javax.microedition.lcdui.Canvas;
 
import javax.microedition.lcdui.Command;
 
import javax.microedition.lcdui.Command;
Line 41: Line 40:
 
import javax.microedition.lcdui.Graphics;
 
import javax.microedition.lcdui.Graphics;
 
import javax.microedition.lcdui.Image;
 
import javax.microedition.lcdui.Image;
 
+
 
import javax.microedition.midlet.MIDlet;
 
import javax.microedition.midlet.MIDlet;
 
import javax.microedition.m3g.AnimationController;
 
import javax.microedition.m3g.AnimationController;
Line 60: Line 59:
 
import javax.microedition.m3g.VertexArray;
 
import javax.microedition.m3g.VertexArray;
 
import javax.microedition.m3g.VertexBuffer;
 
import javax.microedition.m3g.VertexBuffer;
 
+
 
+
 
/**
 
/**
 
  *  
 
  *  
Line 87: Line 86:
 
         canvas3d = new Canvas3D();
 
         canvas3d = new Canvas3D();
 
         iTimer = new Timer();
 
         iTimer = new Timer();
 
+
 
     }
 
     }
 
+
    /**
+
    * Switches a current canvas3d in a display. The Display instance is
+
    * taken from getDisplay() method. This method is used by all actions
+
    * in the design for switching displayable.
+
    * @param alert the Alert which is temporarily set to the display
+
    * @param nextDisplayable the Displayable to be set
+
    */
+
    public void switchDisplayable(Alert alert, Displayable nextDisplayable) {
+
        Display display = getDisplay();
+
        if (alert == null) {
+
            display.setCurrent(nextDisplayable);
+
        } else {
+
            display.setCurrent(alert, nextDisplayable);
+
        }
+
    }
+
 
+
 
     /**
 
     /**
 
     * Returns a display instance.
 
     * Returns a display instance.
Line 113: Line 96:
 
         return Display.getDisplay(this);
 
         return Display.getDisplay(this);
 
     }
 
     }
 
+
 
     /**
 
     /**
 
     * From MIDlet.
 
     * From MIDlet.
Line 124: Line 107:
 
         iTimer.schedule( new MyTimerTask(), 0, 50 );
 
         iTimer.schedule( new MyTimerTask(), 0, 50 );
 
     }
 
     }
 
+
 
     /**
 
     /**
 
     * From MIDlet.
 
     * From MIDlet.
Line 132: Line 115:
 
         //Empty implementation
 
         //Empty implementation
 
     }
 
     }
 
+
 
     /**
 
     /**
 
     * From MIDlet.
 
     * From MIDlet.
Line 151: Line 134:
 
         instance = null;  
 
         instance = null;  
 
     }
 
     }
 
+
 
     /** * Our timer task for providing animation. */  
 
     /** * Our timer task for providing animation. */  
 
     class MyTimerTask extends TimerTask {
 
     class MyTimerTask extends TimerTask {
Line 163: Line 146:
 
         }
 
         }
 
     }
 
     }
 
+
 
     /**
 
     /**
 
     * Inner class for handling the canvas.
 
     * Inner class for handling the canvas.
Line 172: Line 155:
 
         */
 
         */
 
         private Command exitCommand;
 
         private Command exitCommand;
 
+
 
         /**
 
         /**
 
         * Reference to 3D graphics context that can be bound to a rendering  
 
         * Reference to 3D graphics context that can be bound to a rendering  
Line 207: Line 190:
 
         public Canvas3D() {  
 
         public Canvas3D() {  
 
             exitCommand = new Command("Exit", Command.EXIT, 1);
 
             exitCommand = new Command("Exit", Command.EXIT, 1);
 
+
 
             addCommand(exitCommand);
 
             addCommand(exitCommand);
 
              
 
              
 
             // set up this Displayable to listen to command events  
 
             // set up this Displayable to listen to command events  
 
             setCommandListener(this);
 
             setCommandListener(this);
 
+
 
             initialize();
 
             initialize();
 
         }
 
         }
 
+
 
         /**
 
         /**
 
         * Initialize self.
 
         * Initialize self.
Line 222: Line 205:
 
             // get the singleton Graphics3D instance  
 
             // get the singleton Graphics3D instance  
 
             iG3D = Graphics3D.getInstance();  
 
             iG3D = Graphics3D.getInstance();  
 
+
 
             iBackground = backgroundInitialization("/background.png");
 
             iBackground = backgroundInitialization("/background.png");
 
             //Material is an Appearance component encapsulating material  
 
             //Material is an Appearance component encapsulating material  
Line 242: Line 225:
 
             iApplicationTime = 0;
 
             iApplicationTime = 0;
 
             }
 
             }
 
+
 
         /**
 
         /**
 
* From Canvas.
 
* From Canvas.
Line 261: Line 244:
 
             transform.postTranslate(0.0f, 0.0f, 35.0f);  
 
             transform.postTranslate(0.0f, 0.0f, 35.0f);  
 
             iG3D.setCamera(iCamera, transform);
 
             iG3D.setCamera(iCamera, transform);
 
+
 
             //calcuulating parameters for animation according to  
 
             //calcuulating parameters for animation according to  
 
             //current world time
 
             //current world time
 
             iLight.animate(iApplicationTime);
 
             iLight.animate(iApplicationTime);
 
+
 
             // update Light object
 
             // update Light object
 
             iG3D.resetLights();  
 
             iG3D.resetLights();  
 
             iG3D.addLight(iLight, transform);
 
             iG3D.addLight(iLight, transform);
 
+
 
             transform.setIdentity();
 
             transform.setIdentity();
 
             //calcuulating parameters for animation according to  
 
             //calcuulating parameters for animation according to  
Line 279: Line 262:
 
             // update our transform (this will give us a rotating cube)  
 
             // update our transform (this will give us a rotating cube)  
 
             iG3D.render(iAnimatedMesh, transform);
 
             iG3D.render(iAnimatedMesh, transform);
 
+
 
             iG3D.releaseTarget();
 
             iG3D.releaseTarget();
 
         }
 
         }
Line 313: Line 296:
 
             }catch(Exception e) {  
 
             }catch(Exception e) {  
 
                 //TODO: write handler code
 
                 //TODO: write handler code
             }                
+
             }
 
             return material;
 
             return material;
 
         }
 
         }
Line 325: Line 308:
 
             Background background = new Background();
 
             Background background = new Background();
 
             try {
 
             try {
                 // loading image for background with the same approach as texture
+
                 // loading image for background with the same approach as  
                 //image
+
                 //texture image
 
                 Image backImage = null;
 
                 Image backImage = null;
 
                 // load the image for the texture
 
                 // load the image for the texture
Line 335: Line 318:
 
             }catch(Exception e) {  
 
             }catch(Exception e) {  
 
                 //TODO: write handler code
 
                 //TODO: write handler code
             }                
+
             }
 
             return background;
 
             return background;
 
         }
 
         }
Line 416: Line 399:
 
                 127, 0, 0,  127, 0, 0,  127, 0, 0,  127, 0, 0,-127,  
 
                 127, 0, 0,  127, 0, 0,  127, 0, 0,  127, 0, 0,-127,  
 
                 0, 0,-127, 0, 0,-127, 0, 0,-127, 0 };  
 
                 0, 0,-127, 0, 0,-127, 0, 0,-127, 0 };  
 
+
 
             // create a vertex array for the normals of the object  
 
             // create a vertex array for the normals of the object  
 
             VertexArray normArray = new VertexArray(norm.length / 3, 3, 1);  
 
             VertexArray normArray = new VertexArray(norm.length / 3, 3, 1);  
Line 432: Line 415:
 
             // create triangle strips from the contents of the vertex buffer).  
 
             // create triangle strips from the contents of the vertex buffer).  
 
             IndexBuffer indexBuffer = new TriangleStripArray( 0, stripLen );  
 
             IndexBuffer indexBuffer = new TriangleStripArray( 0, stripLen );  
 
+
 
             // per vertex texture coordinates  
 
             // per vertex texture coordinates  
 
             //values represents mapping of texture to vertices of 3d object
 
             //values represents mapping of texture to vertices of 3d object
Line 471: Line 454:
 
             // texture color is to be modulated with the lit material color             
 
             // texture color is to be modulated with the lit material color             
 
             texture.setBlending(Texture2D.FUNC_MODULATE);  
 
             texture.setBlending(Texture2D.FUNC_MODULATE);  
 
+
 
             // create the appearance object
 
             // create the appearance object
 
             //It's a set of component objects that define the rendering  
 
             //It's a set of component objects that define the rendering  
Line 478: Line 461:
 
             cubeAppearance.setTexture(0, texture);  
 
             cubeAppearance.setTexture(0, texture);  
 
             cubeAppearance.setMaterial(material);  
 
             cubeAppearance.setMaterial(material);  
 
+
 
             //creating Mesh object and passing as parameters
 
             //creating Mesh object and passing as parameters
 
             //vertex, index buffers and Appearance component
 
             //vertex, index buffers and Appearance component
Line 506: Line 489:
 
             colorKeyframes.setKeyframe(3, 3000, new float[]{0.0f, 0.0f, 1.0f});
 
             colorKeyframes.setKeyframe(3, 3000, new float[]{0.0f, 0.0f, 1.0f});
 
             colorKeyframes.setKeyframe(4, 4000, new float[]{1.0f, 1.0f, 1.0f});
 
             colorKeyframes.setKeyframe(4, 4000, new float[]{1.0f, 1.0f, 1.0f});
 
+
 
             //Associates a KeyframeSequence with an AnimationController and sets
 
             //Associates a KeyframeSequence with an AnimationController and sets
 
             //the type of animation. In this case it's color animation.             
 
             //the type of animation. In this case it's color animation.             
Line 524: Line 507:
 
             rotationKeyframes.setRepeatMode(KeyframeSequence.LOOP);
 
             rotationKeyframes.setRepeatMode(KeyframeSequence.LOOP);
 
             rotationKeyframes.setDuration(4000);
 
             rotationKeyframes.setDuration(4000);
 
+
 
             //getRotationQuaternion() method converts vector and angle
 
             //getRotationQuaternion() method converts vector and angle
 
             //values to quaternion
 
             //values to quaternion
Line 531: Line 514:
 
             rotationKeyframes.setKeyframe(1, 4000,  
 
             rotationKeyframes.setKeyframe(1, 4000,  
 
                 getRotationQuaternion(359.0f, new float[] {0.0f, 1.0f, 0.0f}));
 
                 getRotationQuaternion(359.0f, new float[] {0.0f, 1.0f, 0.0f}));
 
+
 
             //AnimationTrack associates a KeyframeSequence with an  
 
             //AnimationTrack associates a KeyframeSequence with an  
 
             //AnimationController and sets the type of animation.  
 
             //AnimationController and sets the type of animation.  
Line 539: Line 522:
 
                     new AnimationTrack(rotationKeyframes,  
 
                     new AnimationTrack(rotationKeyframes,  
 
                                         AnimationTrack.ORIENTATION);
 
                                         AnimationTrack.ORIENTATION);
 
+
 
             //creating AnimationController which  
 
             //creating AnimationController which  
 
             //controls the position, speed and weight of an animation sequence
 
             //controls the position, speed and weight of an animation sequence
Line 546: Line 529:
 
             rotationAnimationTrack.setController(animator);
 
             rotationAnimationTrack.setController(animator);
 
             colorAnimationTrack.setController(animator);
 
             colorAnimationTrack.setController(animator);
 
+
 
             //set active time interval for controller
 
             //set active time interval for controller
 
             //8000 is not necessarily in milliseconds, it's abstract world
 
             //8000 is not necessarily in milliseconds, it's abstract world
Line 558: Line 541:
 
             //sequence time must be equal to 0
 
             //sequence time must be equal to 0
 
             animator.setPosition(0, 4000);
 
             animator.setPosition(0, 4000);
 
+
 
             //adding animation tracks to our objects that we
 
             //adding animation tracks to our objects that we
 
             //wanting to animate
 
             //wanting to animate

Revision as of 18:28, 5 December 2008


Article Metadata
Tested with
Devices(s): Nokia N81
CompatibilityArticle
Keywords: javax.microedition.m3g.Graphics3D, javax.microedition.m3g.Canvas, javax.microedition.m3g.Light, javax.microedition.m3g.Transform,

javax.microedition.m3g.Mesh, javax.microedition.m3g.KeyframeSequence, javax.microedition.m3g.AnimationTrack, javax.microedition.m3g.AnimationController,

javax.microedition.m3g.Object3D.addAnimationTrack(), javax.microedition.m3g.Object3D.animate()
Created: (10 Nov 2008)
Last edited: IlGolub (05 Dec 2008)

Overview

This code example represents using of Mobile 3D Graphics API for animation with KeyframeSequence, AnimationTrack and AnimationController classes.

First of all we must define what kind of animation we want to use(see animationInitialization(Light light, Mesh mesh) method). Then we create a KeyframeSequence object which consist of some keyframes with appropriate values and create AnimationTrack object with animation type defining.

Then we create a AnimationController object, tune it, add AnimationTrack objects to 3D entity(like Light, Mesh and others)

Later in paint() method we call animate function for each 3D entity and render the scene.

Source file: AnimationMIDlet.java

import java.io.IOException;
 
import java.util.Timer;
import java.util.TimerTask;
 
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
 
import javax.microedition.midlet.MIDlet;
import javax.microedition.m3g.AnimationController;
import javax.microedition.m3g.AnimationTrack;
import javax.microedition.m3g.Appearance;
import javax.microedition.m3g.Background;
import javax.microedition.m3g.Camera;
import javax.microedition.m3g.Graphics3D;
import javax.microedition.m3g.Image2D;
import javax.microedition.m3g.IndexBuffer;
import javax.microedition.m3g.KeyframeSequence;
import javax.microedition.m3g.Light;
import javax.microedition.m3g.Material;
import javax.microedition.m3g.Mesh;
import javax.microedition.m3g.Texture2D;
import javax.microedition.m3g.Transform;
import javax.microedition.m3g.TriangleStripArray;
import javax.microedition.m3g.VertexArray;
import javax.microedition.m3g.VertexBuffer;
 
 
/**
*
*/

public class AnimationMIDlet extends MIDlet {
/**
* Reference to MIDlet instance for using it inside Canvas3D
*/

static AnimationMIDlet instance;
/**
* Canvas instance using for drawing with m3g
*/

Canvas3D canvas3d;
/**
* Timer object for animation process
*/

Timer iTimer;
 
/**
* The Canvas3D constructor.
*/

public AnimationMIDlet() {
// Set up the user interface.
AnimationMIDlet.instance = this;
canvas3d = new Canvas3D();
iTimer = new Timer();
 
}
 
/**
* Returns a display instance.
* @return the display instance.
*/

public Display getDisplay () {
return Display.getDisplay(this);
}
 
/**
* From MIDlet.
* Called when MIDlet is started.
* Sets object from canvas3d variable as current displayable.
* Schedules a MyTimerTask timer task.
*/

public void startApp() {
Display.getDisplay(this).setCurrent(canvas3d);
iTimer.schedule( new MyTimerTask(), 0, 50 );
}
 
/**
* From MIDlet.
* Called when MIDlet is paused.
*/

public void pauseApp() {
//Empty implementation
}
 
/**
* From MIDlet.
* Called to signal the MIDlet to terminate.
* @param unconditional if true, then the MIDlet has to be unconditionally
* terminated and all resources has to be released.
*/

public void destroyApp(boolean unconditional) {
//Empty implementation
}
 
/**
* Quit the MIDlet.
*/

public static void quitApp() {
instance.destroyApp(true);
instance.notifyDestroyed();
instance = null;
}
 
/** * Our timer task for providing animation. */
class MyTimerTask extends TimerTask {
/**
* From TimerTask.
*/

public void run() {
if( canvas3d != null ) {
canvas3d.repaint();
}
}
}
 
/**
* Inner class for handling the canvas.
*/

class Canvas3D extends Canvas implements CommandListener{
/**
* exit midlet command
*/

private Command exitCommand;
 
/**
* Reference to 3D graphics context that can be bound to a rendering
* target. All rendering is done through the render methods
* in this class
*/

private Graphics3D iG3D;
/**
* Defines the position of the viewer in the scene and
* the projection from 3D to 2D.
*/

private Camera iCamera;
/**
* Represents different kinds of light sources.
*/

private Light iLight;
/**
* Defines whether and how to clear the viewport. It can be
* image or color for solid filling.
*/

private Background iBackground;
/**
* absolute counter of animation in world units
*/

int iApplicationTime;
/**
* Mesh object that represents a cube
*/

Mesh iAnimatedMesh;
 
/**
* Construct the Displayable.
*/

public Canvas3D() {
exitCommand = new Command("Exit", Command.EXIT, 1);
 
addCommand(exitCommand);
 
// set up this Displayable to listen to command events
setCommandListener(this);
 
initialize();
}
 
/**
* Initialize self.
*/

void initialize() {
// get the singleton Graphics3D instance
iG3D = Graphics3D.getInstance();
 
iBackground = backgroundInitialization("/background.png");
//Material is an Appearance component encapsulating material
//attributes for lighting computations.
Material material = materialInitialization(0xFFFFFFFF,
0xFFFFFFFF, 100.0f);
iCamera = cameraInitialization(70.0f);
iLight = lightInitialization(0xFFFFFFFF, Light.SPOT);
 
try {
//creating of cube object as Mesh
iAnimatedMesh = сubeMeshInitialization(material);
 
animationInitialization(iLight, iAnimatedMesh);
}catch(Exception e) {
//TODO: write handler code
}
 
iApplicationTime = 0;
}
 
/**
* From Canvas.
* Rendering the scene
*/

protected void paint(Graphics g) {
//incrementing world time
iApplicationTime = iApplicationTime + 50;
 
// Bind the Graphics of this Canvas to Graphics3D.
//We enable depth buffer, dithering and true color rendering(if it
//supported of course)
iG3D.bindTarget(g, true, Graphics3D.DITHER | Graphics3D.TRUE_COLOR);
// clear the color and depth buffers
iG3D.clear(iBackground);
// set up the camera in the desired position
Transform transform = new Transform();
transform.postTranslate(0.0f, 0.0f, 35.0f);
iG3D.setCamera(iCamera, transform);
 
//calcuulating parameters for animation according to
//current world time
iLight.animate(iApplicationTime);
 
// update Light object
iG3D.resetLights();
iG3D.addLight(iLight, transform);
 
transform.setIdentity();
//calcuulating parameters for animation according to
//current world time
iAnimatedMesh.animate(iApplicationTime);
// In immediate mode, node transforms are ignored, so we get
// our animated transformation into a local transform object
iAnimatedMesh.getCompositeTransform(transform);
// update our transform (this will give us a rotating cube)
iG3D.render(iAnimatedMesh, transform);
 
iG3D.releaseTarget();
}
/**
* From CommandListener.
* @param command
* @param displayable
*/

public void commandAction(Command command, Displayable displayable) {
if (command == exitCommand) {
// exit the MIDlet
AnimationMIDlet.quitApp();
}
}
/**
* Creating a Material object
* @param diffuseColor is specifying that the diffuse color component
* is to be set to a Material object
* @param specularColor is specifying that the specular color component
* is to be set to a Material object
* @param shininess is the specular exponent term in the
* lighting equation
* @return the prepeared Material object
*/

private Material materialInitialization(int diffuseColor,
int specularColor, float shininess) {
Material material = new Material();
try{
//set color for Material object. if
material.setColor(Material.DIFFUSE, diffuseColor);
material.setColor(Material.SPECULAR, specularColor);
material.setShininess(shininess);
}catch(Exception e) {
//TODO: write handler code
}
return material;
}
/**
* Method creates a new Background object with image instead of
* background color
* @param imageFileName is the name of image file
* @return the prepeared Background object
*/

private Background backgroundInitialization(String imageFileName) {
Background background = new Background();
try {
// loading image for background with the same approach as
//texture image
Image backImage = null;
// load the image for the texture
backImage = Image.createImage(imageFileName);
Image2D backgroundImage2D = new Image2D( Image2D.RGB, backImage);
background.setImageMode(Background.BORDER, Background.BORDER);
background.setImage(backgroundImage2D);
}catch(Exception e) {
//TODO: write handler code
}
return background;
}
/**
* Creates a camera object with perspective projection
* @param angleOfView is the camera field of view
* @return the prepeared Camera object
*/

private Camera cameraInitialization(float angleOfView) {
Camera camera = new Camera();
try{
camera.setPerspective( angleOfView,
(float)getWidth()/ (float)getHeight(), // aspectRatio
1.0f, // near clipping plane
1000.0f ); // far clipping plane
}catch(Exception e) {
//TODO: write handler code
}
return camera;
}
/**
* Creates a light source object
* @param color is the color component of light
* @param lightType is the type of light source(like SPOT, OMNI and
* others)
* @return the prepeared Light object
*/

private Light lightInitialization(int color, int lightType) {
// create a light object
Light light = new Light();
try{
// white light. Later this parameter will be animated
light.setColor(color);
//Sets the intensity of light
light.setIntensity(1.0f);
//sets the spot type for this light
light.setMode(lightType);
//sets the spot exponent, that controls the distribution of the
//intensity of light within the spot cone
light.setSpotExponent(1.0f);
//sets the spot angle
light.setSpotAngle(45);
}catch(Exception e) {
//TODO: write handler code
}
return light;
}
/**
* Creates Cube Mesh
* @param material is the Appearance component of new Mesh
* @return the prepeared Mesh object
*/

private Mesh сubeMeshInitialization(Material material) {
// initialize some arrays for our object (cube)
// Each line in this array declaration represents a triangle
// strip for one side of a cube.
// 1 * * * * * 0
// * * *
// * * *
// * * *
// 3 * * * * * 2
// The ascii diagram above represents the vertices in the first line
// (the first tri-strip)
short[] vert = {
10, 10, 10, -10, 10, 10, 10,-10, 10, -10,-10, 10, // front
-10, 10,-10, 10, 10,-10, -10,-10,-10, 10,-10,-10, // back
-10, 10, 10, -10, 10,-10, -10,-10, 10, -10,-10,-10, // left
10, 10,-10, 10, 10, 10, 10,-10,-10, 10,-10, 10, // right
10, 10,-10, -10, 10,-10, 10, 10, 10, -10, 10, 10, // top
10,-10, 10, -10,-10, 10, 10,-10,-10, -10,-10,-10 }; // bottom
// create a VertexArray to hold the vertices for the object
VertexArray vertArray = new VertexArray(vert.length / 3, 3, 2);
vertArray.set(0, vert.length/3, vert);
// normal vectors for the cube. used for lighting
byte[] norm = {
0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0, 127,
0, 0,-127, 0, 0,-127, 0, 0,-127, 0, 0,-127,
-127, 0, 0, -127, 0, 0, -127, 0, 0, -127, 0, 0,
127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0, 0,
127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0,-127,
0, 0,-127, 0, 0,-127, 0, 0,-127, 0 };
 
// create a vertex array for the normals of the object
VertexArray normArray = new VertexArray(norm.length / 3, 3, 1);
normArray.set(0, norm.length/3, norm);
// the length of each triangle strip
int[] stripLen = { 4, 4, 4, 4, 4, 4 };
 
//Creating of instance of TriangleStripArray
//(derived from IndexBuffer). It
//represents an array of triangle strips.
//In a triangle strip, the first three vertex indices define
//the first triangle. Each subsequent index together with the two
//previous indices defines a new triangle.
// create the index buffer for our object (this tells how to
// create triangle strips from the contents of the vertex buffer).
IndexBuffer indexBuffer = new TriangleStripArray( 0, stripLen );
 
// per vertex texture coordinates
//values represents mapping of texture to vertices of 3d object
short[] tex = {
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1,
1, 0, 0, 0, 1, 1, 0, 1 };
// create a vertex array for the texture coordinates of the object
VertexArray texArray = new VertexArray(tex.length / 2, 2, 2);
texArray.set(0, tex.length/2, tex);
//VertexBuffer holds references to VertexArrays that contain the
//positions, colors, normals, and texture coordinates for a set
//of vertices create the VertexBuffer for our object
VertexBuffer vertexBuffer = new VertexBuffer();
vertexBuffer.setPositions(vertArray, 1.0f, null);
// unit scale, zero bias
vertexBuffer.setNormals(normArray);
vertexBuffer.setTexCoords(0, texArray, 1.0f, null);
//Texture creating
Image textureImage = null;
try {
// load the image for the texture
textureImage = Image.createImage("/texture.png");
} catch (IOException ex) {
ex.printStackTrace();
}
// create the Image2D (we need this so we can make a Texture2D)
Image2D image2D = new Image2D( Image2D.RGB, textureImage );
// create the Texture2D and enable mipmapping
Texture2D texture = new Texture2D( image2D );
texture.setFiltering(Texture2D.FILTER_LINEAR,
Texture2D.FILTER_LINEAR);
//specifying that the texture image is to be repeated only once
texture.setWrapping(Texture2D.WRAP_CLAMP, Texture2D.WRAP_CLAMP);
// texture color is to be modulated with the lit material color
texture.setBlending(Texture2D.FUNC_MODULATE);
 
// create the appearance object
//It's a set of component objects that define the rendering
//attributes. Using during render operation.
Appearance cubeAppearance = new Appearance();
cubeAppearance.setTexture(0, texture);
cubeAppearance.setMaterial(material);
 
//creating Mesh object and passing as parameters
//vertex, index buffers and Appearance component
Mesh mesh = new Mesh(vertexBuffer, indexBuffer, cubeAppearance);
return mesh;
}
/**
*
* @param light is the Light object for color animation
* @param mesh is the Mesh object for rotation animation
*/

private void animationInitialization(Light light, Mesh mesh) {
//Sequence of keyframes for rotation of cube
//creating color KeyframeSequence object
//with 5 keyframes with 3 components in each
//and setting the intepolation type
KeyframeSequence colorKeyframes = new KeyframeSequence(5, 3,
KeyframeSequence.LINEAR);
//then setting the duration of color animation
colorKeyframes.setDuration(4000);
//this animation will play only once without repeat
colorKeyframes.setRepeatMode(KeyframeSequence.CONSTANT);
//setting index, timestamp, and components values for 5 keyframes
colorKeyframes.setKeyframe(0, 0, new float[]{1.0f, 1.0f, 1.0f});
colorKeyframes.setKeyframe(1, 1000, new float[]{1.0f, 0.0f, 0.0f});
colorKeyframes.setKeyframe(2, 2000, new float[]{0.0f, 1.0f, 0.0f});
colorKeyframes.setKeyframe(3, 3000, new float[]{0.0f, 0.0f, 1.0f});
colorKeyframes.setKeyframe(4, 4000, new float[]{1.0f, 1.0f, 1.0f});
 
//Associates a KeyframeSequence with an AnimationController and sets
//the type of animation. In this case it's color animation.
//creating AnimationTrack object for color animation
AnimationTrack colorAnimationTrack =
new AnimationTrack(colorKeyframes, AnimationTrack.COLOR);
 
//Sequence of keyframes for color transition for light
//creating color KeyframeSequence object
//with 2 keyframes and 4 components in each
//and setting the intepolation type to SLERP
//that specifies spherical linear interpolation of quaternions
KeyframeSequence rotationKeyframes =
new KeyframeSequence(2, 4, KeyframeSequence.SLERP);
//this animation will be repeating while animation inside active
//interval
rotationKeyframes.setRepeatMode(KeyframeSequence.LOOP);
rotationKeyframes.setDuration(4000);
 
//getRotationQuaternion() method converts vector and angle
//values to quaternion
rotationKeyframes.setKeyframe(0, 0,
getRotationQuaternion(0.0f, new float[] {0.0f, 1.0f, 0.0f}));
rotationKeyframes.setKeyframe(1, 4000,
getRotationQuaternion(359.0f, new float[] {0.0f, 1.0f, 0.0f}));
 
//AnimationTrack associates a KeyframeSequence with an
//AnimationController and sets the type of animation.
//In this case it's orientation animation.
//creating AnimationTrack object for orientation animation
AnimationTrack rotationAnimationTrack =
new AnimationTrack(rotationKeyframes,
AnimationTrack.ORIENTATION);
 
//creating AnimationController which
//controls the position, speed and weight of an animation sequence
AnimationController animator = new AnimationController();
//set controller for animation tracks
rotationAnimationTrack.setController(animator);
colorAnimationTrack.setController(animator);
 
//set active time interval for controller
//8000 is not necessarily in milliseconds, it's abstract world
//time
animator.setActiveInterval(0, 8000);
//set speed to half of normal
//animator.setSpeed(0.5f, 0);
//Sets a new playback position, relative to world time
//0 - desired playback position in sequence time units
//4000 - the world time at which the
//sequence time must be equal to 0
animator.setPosition(0, 4000);
 
//adding animation tracks to our objects that we
//wanting to animate
mesh.addAnimationTrack(rotationAnimationTrack);
light.addAnimationTrack(colorAnimationTrack);
}
/**
* Calculates the quaternion for a rotation of
* angle degrees about the vector.
* @param angle - is an angle of rotation round of vector
* @param vector - 3D vector of rotation
* @return quaternion of rotation
*/

private float[] getRotationQuaternion(float angle, float[] vector) {
float[] quaternion = new float[4];
double angleRadians = Math.toRadians(angle)/2.0;
//i component
quaternion[0] = vector[0] * (float)Math.sin(angleRadians);
//j component
quaternion[1] = vector[1] * (float)Math.sin(angleRadians);
//k component
quaternion[2] = vector[2] * (float)Math.sin(angleRadians);
//w scalar component
quaternion[3] = (float)Math.cos(angleRadians);
return quaternion;
}
}
}


Postconditions

As result we have a MIDlet which draws a rotated cube mesh and animated color of light source

See also

Supplementary material

You can download this MIDlet, source code and resources from here - Simple Animation.zip

187 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×