M3G Tutorial: Advanced Article 6 Animation

Source: Internet
Author: User

The animation Data Structure in M3G is as follows:

[Load world node]

You can use the M3G viewer to view the M3G file converted by M3G converter. We will find that camera in the M3G file is not under the world tree, but is in the same level as the world tree. Because jsr184 requires that all model information be placed under the world tree during rendering, we need to get the world node first. There are two methods:

① Traverse the object3d array and compare the userid of each element. If it is the useid of the world node, this element is taken out;
② Traverse the object3d array and compare whether each element is an instance of the world class. Since the world node is the root node of the scenario, in this object3d array, there should also be only one instance object of the world class.

The first method must be obtained by viewing the userid of the world node in the file, and the second method is easier to operate. The Code is as follows:

/** Loads our world */<br/> private void loadworld () {<br/> try {<br/> // loading the world is very simple. note that I like to use a <br/> // res-folder that I keep all files in. if you normally just put <br/> // your <br/> // Resources in the project root, then load it from the root. <br/> object3d [] buffer = loader. load ("/axe. m3G "); </P> <p> // find the world node, best to do it the" safe "way <br/> (INT I = 0; I <buffer. length; I ++) {<br/> If (buffer [I] instanceof world) {<br/> world = (World) buffer [I]; <br/> break; <br/>}</P> <p> // clean objects <br/> buffer = NULL; <br/>} catch (exception e) {<br/> // error! <Br/> system. Out. println ("loading error! "); <Br/> reportexception (E); <br/>}< br/>}

In jsr184, three key frame animation classes are used: animationtrack, animationcontroller, and keyframesquence:

Animationtrack: A Collection class (composition) used to combine animationcontroller, keyframesquence, and a specific property (target property, this structure also enables the same animationcontroller and keyframesquence to be reused by different key frame animations. In each object3d object, a set of animationtrack sequences are managed through the addanimationtrack and removeanimationtrack methods. When the animate method is used to calculate the Key Frame Animation of the object3d object, all animationtracks in the sequence are calculated in sequence. If the object3d object is referenced by another object3d object, the animate methods of all referenced object3d objects are also executed in sequence.

Animationcontroller: ing from worldtime to squencetime by specifying the sampling point and sampling speed to control the playing effect of the animation, such as pause, continue, fast forward, and backward.

The animationcontroller has an activation period attribute (implemented through setactiveinterval (INT, INT). It controls the activation status of the animationcontroller by specifying the minimum and maximum world time values. If the animation controller is inactive at a certain time, the system ignores it during animation computation.

In addition, the animationcontroller has a weight attribute because the system merges all animation computing results related to this attribute During calculation of an object attribute, weight indicates the proportion of the animationcontroller in this calculation. Specifically, the calculation of a scalar property P is like this: P = sum [wipi].

Animationcontroller maps the world time value passed in the object3d. animate () method to the sequence time value. Sequence time is mainly used to sample animation data of key frames. Sequence time is calculated every time the object's animate () method is called, rather than store it internally, to avoid the accumulation of errors and the resulting series of conditions. This design simplifies the animation system, enables the animation system to become stateless (compared with the state machine), and is more efficient.

The ing from world time to sequence time is calculated by the three constants in the animationcontroller and the world time passed into the animate () method. The formula is as follows:

The reference values T [sref] and T [Wref] are specified through the setposition () method, while the speed is set by setspeed () specify the method (note that changing the speed will affect T [sref] and T [Wref] values ).

Note: although the time unit here is not explicitly stated in the API and documentation, we strongly recommend that you use this default time unit. Of course, if you really need to use a specific time unit, the animation system still supports it.

Keyframesquence: used to save the values of all key frames, specify the key frame loop mode, and calculate the interpolation method.

In both the instant and retained modes, the animation data of an object is calculated by calling the animate () method of the object3d object. You can call either world. animate () or the animate () method of the corresponding object3d object.

[Example]

Run the following code to convert a light from red to green and move it along a curve path:

During initialization:

Light = new light (); // create a light node </P> <p> // load a motion path from a stream, assuming it's the first object there </P> <p> object3d [] objects = loader. load ("http://www.ex.com/ex.m3g"); <br/> keyframesequence motion = (keyframesequence) objects [0]; </P> <p> // create a color keyframe sequence, with keyframes at 0 Ms <br/> // and 500 MS, and a total duration of 1000 ms. the animate <br/> // method will throw an exception if it encounters a <br/> // keyframesequence whose duration has not been set or whose <br/> // keyframes are out of order. note that the loader <br/> // automatically validates any sequences that are loaded from <br/> // a file. </P> <p> keyframesequence blinking = new keyframesequence (2, 3, keyframesequence. linear); <br/> blinking. setkeyframe (0, 0, new float [] {1.0f, 0.0f, 0.0f}); <br/> blinking. setkeyframe (1,500, new float [] {0.0f, 1.0f, 0.0f}); <br/> blinking. setduration (1000); </P> <p> animationtrack blink = new animationtrack (blinking, animationtrack. color); <br/> animationtrack move = new animationtrack (motion, animationtrack. translation); <br/> light. addanimationtrack (blink); <br/> light. addanimationtrack (MOVE ); </P> <p> // create an animationcontroller and make it control both the <br/> // blinking and the movement of our light </P> <p> animationcontroller lightanim = new animationcontroller (); <br/> blink. setcontroller (lightanim); <br/> move. setcontroller (lightanim); </P> <p> // start the animation when world time reaches 2 seconds, stop <br/> // at 5 s. there is only one reference point for this <br/> // Animation: sequence time must be zero at World Time 2000 <br/> // Ms. the animation will be running at normal speed (1.0, the <br/> // default ). </P> <p> lightanim. setactiveinterval (2000,500 0); <br/> lightanim. setpositions (0, 2000 );

Rendering time:

Apptime + = 30; // advance time by 30 MS each frame <br/> light. animate (apptime); </P> <p> // assume 'mygraphics3d 'is the graphics3d object we draw. <br/> // in Immediate Mode, node transforms are ignored, so we get <br/> // Our animated transformation into a local transform object, <br/> // "lighttoworld ". as its name implies, the transformation is <br/> // from the light node's local coordinates to World Space. </P> <p> light. gettransform (lighttoworld); <br/> mygraphics3d. resetlights (); <br/> mygraphics3d. addlight (light, lighttoworld );

[Example: Play kangaroo beat animation]

Package study. pogoroo; </P> <p> Import javax. microedition. lcdui. graphics; <br/> Import javax. microedition. lcdui. game. gamecanvas; <br/> Import javax. microedition. m3G. animationcontroller; <br/> Import javax. microedition. m3G. animationtrack; <br/> Import javax. microedition. m3G. camera; <br/> Import javax. microedition. m3G. graphics3d; <br/> Import javax. microedition. m3G. group; <br/> Import javax. microedition. m3G. ke Yframesequence; <br/> Import javax. microedition. m3G. loader; <br/> Import javax. microedition. m3G. object3d; <br/> Import javax. microedition. m3G. world; </P> <p> public class m1_canvas extends gamecanvas implements runnable {</P> <p> Public static final int FPS = 50; // Number of frames drawn per second </P> <p> // thread-Control <br/> Boolean running = false; </P> <p> Boolean done = true; </P> <p> // userids for objects we use in the scene. <br/> Static final int pogoroo_transform_id = 347178853; <br/> static final int roo_bounce_id = 418071423; </P> <p> // control objects for game play <br/> // Control for 'roo-group transform and cameras <br/> private animationcontroller animroo = NULL; <br/> private group branch o = NULL; <br/> private int animtime = 0; <br/> private int animlength = 0; <br/> private int animlasttime = 0; <br/> int viewpo Rt_x; <br/> int viewport_y; <br/> int viewport_width; <br/> int viewport_height; </P> <p> // key array <br/> private Boolean [] Key = new Boolean [5]; </P> <p> // key constants <br/> Public static final int fire = 0; <br/> Public static final int up = 1; <br/> Public static final int down = 2; <br/> Public static final int left = 3; <br/> Public static final int right = 4; </P> <p> // camera rotation <br/> private Float camrot = 0.0f; </P> <p> private graphics3d g3d; <br/> private world; <br/> private Boolean runnable = true; <br/> private thread; <br/> private camera; </P> <p> protected malong canvas () {<br/> super (false ); <br/> setfullscreenmode (true); <br/> g3d = graphics3d. getinstance (); </P> <p> // load our world <br/> loadworld (); </P> <p> // load our camera <br/> loadcamera (); </P> <p> getobjects (); </P> <p> Setu Paspectratio (); <br/>}</P> <p>/** loads our camera */<br/> private void loadcamera () {<br/> // bad! <Br/> If (World = NULL) <br/> return; </P> <p> // get the active camera from the world <br/> camera = World. getactivecamera (); <br/>}</P> <p>/** loads our world */<br/> private void loadworld () {<br/> try {<br/> // loading the world is very simple. note that I like to use a <br/> // res-folder that I keep all files in. if you normally just put <br/> // your <br/> // Resources in the project root, then load It from the root. <br/> object3d [] buffer = loader. load ("/pogoroo. m3G "); </P> <p> // find the world node, best to do it the" safe "way <br/> for (INT I = 0; I <buffer. length; I ++) {<br/> If (buffer [I] instanceof world) {<br/> world = (World) buffer [I]; <br/> break; <br/>}</P> <p> // clean objects <br/> buffer = NULL; <br/>} catch (exception e) {<br/> // error! <Br/> system. Out. println ("loading error! "); <Br/>}</P> <p>/** <br/> * Make sure that the content is rendered with the correct aspect ratio. <br/> */<br/> void setupaspectratio () {<br/> viewport_x = 0; <br/> viewport_y = 0; <br/> viewport_width = getwidth (); <br/> viewport_height = getheight (); </P> <p> float [] Params = new float [4]; <br/> int type = camera. getprojection (Params); </P> <p> If (type! = Camera. generic) {<br/> // calculate window aspect ratio <br/> float waspect = viewport_width/viewport_height; </P> <p> If (waspect <Params [1]) {<br/> float Height = viewport_width/Params [1]; <br/> viewport_height = (INT) height; <br/> viewport_y = (getheight ()-viewport_height) /2; <br/>}else {<br/> float width = viewport_height * Params [1]; <br/> viewport_width = (INT) width; <br/> viewpo Rt_x = (getwidth ()-viewport_width)/2; <br/>}</P> <p>/** <br/> * getobjects () <br/> * Get objects from the scene tree for use in the game AI <br/> */<br/> Public void getobjects () {<br/> try {<br/> Foreign o = (Group) World. find (pogoroo_transform_id); <br/> animroo = (animationcontroller) World. find (roo_bounce_id); </P> <p> // get length of animation <br/> animationtrack track = ACR OO. getanimationtrack (0); <br/> animlength = 1000; // default length, 1 second </P> <p> If (track! = NULL) {<br/> keyframesequence Ks = track. getkeyframesequence (); </P> <p> If (Ks! = NULL) {<br/> animlength = Ks. getduration (); <br/>}< br/>} catch (exception e) {<br/> E. printstacktrace (); <br/>}</P> <p>/** <br/> * animateroo () <br/> * makes sure that the hopping animation loops correctly. <br/> */<br/> private void animateroo (INT worldtime) {<br/> // control the kangaroo animation sequence <br/> If (animlasttime = 0) {<br/> animlasttime = worldtime; <br />}</P> <p> animtime + = (worldtime-animlasttime ); </P> <p> // initialise animation at end of sequence <br/> If (animtime> animlength) // sequence is ~ 1000 ms <br/> {<br/> animroo. setactiveinterval (worldtime, worldtime + 2000); <br/> // setposition (float sequencetime, int worldtime) <br/> // sets a new playback position, relative to World Time, for this animation controller. <br/> animroo. setposition (0, worldtime); <br/> animtime = 0; <br/>}</P> <p> // update storage of last position and time <br/> animlasttime = worldtime; <br/>}</P> <p> private void Movecamera () {<br/> // Check controls <br/> If (Key [left]) {<br/> camrot + = 5.0f; <br/>} else if (Key [right]) {<br/> camrot-= 5.0f; <br/>}</P> <p> // set the orientation <br/> camera. setorientation (camrot, 0.0f, 1.0f, 0.0f); </P> <p> // if the user presses the fire key, let's quit <br/> If (Key [Fire]) <br/> system. out. println ("fire"); <br/>}</P> <p> protected void process () {<br/> int keys = getkeystates (); </P> <p> If (Keys & gamecanvas. fire_pressed )! = 0) <br/> key [Fire] = true; <br/> else <br/> key [Fire] = false; </P> <p> If (Keys & gamecanvas. up_pressed )! = 0) <br/> key [Up] = true; <br/> else <br/> key [Up] = false; </P> <p> If (Keys & gamecanvas. down_pressed )! = 0) <br/> key [Down] = true; <br/> else <br/> key [Down] = false; </P> <p> If (Keys & gamecanvas. left_pressed )! = 0) <br/> key [left] = true; <br/> else <br/> key [left] = false; </P> <p> If (Keys & gamecanvas. right_pressed )! = 0) <br/> key [right] = true; <br/> else <br/> key [right] = false; <br/>}</P> <p> Public void run () {<br/> graphics G = getgraphics (); <br/> while (runnable) {<br/> long starttime = system. currenttimemillis (); </P> <p> // call the process method (computes keys) <br/> process (); </P> <p> // move the camera around <br/> movecamera (); </P> <p> try {<br/> // first bind the graphics object. we use our pre-defined Rendering <Br/> // hints. <br/> g3d. bindtarget (g); </P> <p> int ST = (INT) starttime; <br/> // update the control and game AI <br/> animateroo (ST); <br/> // update the world to the current time. <br/> world. animate (ST); </P> <p> g3d. setviewport (viewport_x, viewport_y, viewport_width, viewport_height); <br/> // now, just render the world. simple as pie! <Br/> g3d. render (World); <br/>}finally {<br/> g3d. releasetarget (); <br/>}< br/> flushgraphics (); </P> <p> long endtime = system. currenttimemillis (); <br/> long costtime = endtime-starttime; <br/> If (costtime <1000/FPs) <br/>{< br/> try {<br/> thread. sleep (1000/FPS-costtime); <br/>}< br/> catch (exception e) {<br/> E. printstacktrace (); <br/>}< br/> system. out. println ("canvas stopped"); </P> <p >}</P> <p> Public void start () <br/>{< br/> thread = new thread (this); <br/> thread. start (); <br/>}</P> <p> Public void stop () <br/>{< br/> This. runnable = false; <br/> try {<br/> thread. join (); <br/>}catch (interruptedexception e) {<br/> E. printstacktrace (); <br/>}</P> <p >}< br/>

The node tree relationship of pogoroo. M3G is as follows:

The effect is as follows:

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.