First, brief
Now that you are familiar with the 3D API and understand how 3D graphics are added to mobile Java applications. The following will continue to show you how to use 3D modeling software to make coding and design simpler.
Today, 3D Graphics are almost a key part of any game, and even some applications have succeeded by describing information in 3D form. As mentioned earlier, it is slow and complex to build all 3D objects in both immediate and manual encoding. All corner points of a polygon in an application must be encoded independently in the array. In JSR 184, this is called immediate mode.
Another, more advanced pattern is called retention mode, which allows designers to design scene diagrams using a three-dimensional modeling software such as 3D Max Studio, and then apply them to programs.
Second, 3D editor
Today, the most popular commercial animation software should be 3D Studio Max, which supports the output model or scene map to the m3g format (the file format specified in JSR 184). The file format is specifically designed to apply to the specific needs of mobile devices. However, 3D Studio Max is very expensive, and even if it is a good tool, it may not be suitable for anyone.
Superscape Company has its own swerve product family (Swerve Studio,swerve client,swerve Content) to help software developers develop native applications based on 3D java. Unfortunately, swerve Studio is only suitable for a limited number of developers who are very familiar with Superscape.
There is also a free tool to choose from: Blender. Blender is an open source 3D modeling tool, but it's quite powerful. You can use blender for any 3D design-from simple styling to full animation. Although there is no output tool to output the blender model to the m3g file, there may soon be some tools available (because blender is open source).
third, modeling
How do I use m3g files in a MIDP application? First, you need a m3g file that already has some kind of 3D model. You can use Google engine to quickly find out, or you can use the Wirelesstoolkit 2.2 (under the Demo3d folder) development package with the release of ready-made files. In this article, we will make a deep modification (simplification) of the Sun's Pogoroo routines (editor's note: Sun Development Toolkit self-taking routines). We don't let it move or do anything fancy, but just show the objects on the screen.
Iv. loading World
First, you want to load the world from the M3d file. In the pogoroo.m3g file, you will see a kangaroo jumping on a single spring stilt pole with a green side. The following list 1 invokes method load () for the loader class.
Listing 1. Load
try {
Load World from M3d file
MyWorld = (World) loader.load ("/pogoroo.m3g") [0];
GetObjects ();
Setupaspectratio ();
}
catch (Exception e) {
E.printstacktrace ();
}
v. Acquiring objects from the 3D world
The 3D world has already been loaded, and now you have to get each object from it (see Listing 2). Here, there are four objects in the 3D world, one of which is information about animations (kangaroos jumping on one foot). You can use the world's Find () method to get these objects.
Listing 2. Getting objects from 3D world
try {
Troo = (Group) myworld.find (Pogoroo);
Tcams = (Group) myworld.find (CAMERA);
Acroo = (Group) myworld.find (TRANSFORM);
Animroo = (Animationcontroller) myworld.find (ROO);
Get the length of the animation
Animationtrack track = acroo.getanimationtrack (0);
animlength = 1000; Default length is 1 seconds
if (track!= null) {
Keyframesequence KS = Track.getkeyframesequence ();
if (KS!= null) animlength = Ks.getduration ();
}
}
catch (Exception e) {
E.printstacktrace ();
}
VI. Set window width and height ratio
You must set the width of the window to allow the object to be properly shaded. The code in Listing 3 is unchanged-basically the same as the sun example. First, check the width and height of the canvas, and then calculate the width-height ratio based on the type of camera.
Listing 3. Set width to height ratio
void Setupaspectratio () {
viewport_x = 0;
viewport_y = 0;
Viewport_width = Mycanvas.getwidth ();
Viewport_height = Mycanvas.getheight ();
Camera cam = Myworld.getactivecamera ();
float[] params = new FLOAT[4];
int type = cam.getprojection (params);
if (type!= camera.generic) {
Calculates the height ratio of a window
float Waspect=viewport_width/viewport_height;
if (Waspect<params[1]) {
float height = viewport_width/params[1];
viewport_height= (int) height;
Viewport_y= (Mycanvas.getheight ()-viewport_height)/2;
}
else {
Float width = viewport_height*params[1];
viewport_width= (int) width;
Viewport_x= (Mycanvas.getwidth ()-viewport_width)/2;
}
}
}
Seven, refresh the view
To refresh the view, you can use TimerTask to invoke the repaint () method of the canvas. Another approach is to use the thread directly, and then create the Examplecanvas (the name of the canvas class) to implement the Runnable interface.
Listing 4. Refresh View
Private class Refreshtask extends TimerTask
{
public void Run () {
if (MyCanvas!= null && mygraphics3d!= null && myworld!= null) {
int starttime = (int) system.currenttimemillis ();
int validity = Myworld.animate (starttime);
Mycanvas.repaint (viewport_x, viewport_y, Viewport_width, viewport_height);
}
}
}
Viii. Complete routine Code Analysis
In Listing 5, you'll see the full code for the application. Although longer, it is much simpler than the sun example. You can practice your MIDP skills by adding some action and logic to your application.
Listing 5. The complete routine code
Package com.kontio;
Import javax.microedition.midlet.*;
Import javax.microedition.lcdui.*;
Import java.lang.IllegalArgumentException;
Import java.io.*;
Import java.util.*;
Import javax.microedition.m3g.*;
public class Example3d extends MIDlet implements commandlistener{
The UserID of the objects we use in the scene
static final int pogoroo = 554921620;
static final int CAMERA = 769302310;
static final int TRANSFORM = 347178853;
static final int ROO = 418071423;
Private Display mydisplay = null;
Private Examplecanvas MyCanvas = null;
Private Timer Myrefreshtimer = new timer ();
Private TimerTask myrefreshtask = null;
Private command Exitcommand = new Command ("Exit", Command.item, 1);
Graphics3d mygraphics3d = Graphics3d.getinstance ();
World myworld = null;
Private Animationcontroller Animroo = null;
Private Group Troo = null;
Private Group tcams = null;
Private Group Acroo = null;
private int animlength = 0;
int viewport_x;
int viewport_y;
int viewport_width;
int viewport_height;
Public Example3d () {
Super ();
Mydisplay = Display.getdisplay (this);
MyCanvas = new Examplecanvas (this);
Mycanvas.setcommandlistener (this);
Mycanvas.addcommand (Exitcommand);
}
public void startApp () throws midletstatechangeexception{
Mydisplay.setcurrent (MyCanvas);
try{
Load the world from a file
MyWorld = (World) loader.load ("/pogoroo.m3g") [0];
GetObjects ();
Setupaspectratio ();
}
catch (Exception e) {
E.printstacktrace ();
}
Myrefreshtask = new Refreshtask ();
Schedule an important execution timer to display a frame rate of 20fps.
Myrefreshtimer.schedule (myrefreshtask, 0, 50);
}
void Setupaspectratio () {
viewport_x = 0;
viewport_y = 0;
Viewport_width = Mycanvas.getwidth ();
Viewport_height = Mycanvas.getheight ();
Camera cam = Myworld.getactivecamera ();
float[] params = new FLOAT[4];
int type = cam.getprojection (params);
if (type!= camera.generic) {
Calculate the width and height ratio of a window
float Waspect=viewport_width/viewport_height;
if (Waspect<params[1]) {
float height = viewport_width/params[1];
viewport_height= (int) height;
Viewport_y= (Mycanvas.getheight ()-viewport_height)/2;
}
else{
Float width = viewport_height*params[1];
viewport_width= (int) width;
Viewport_x= (Mycanvas.getwidth ()-viewport_width)/2;
}
}
}
public void GetObjects () {
try{
Troo = (Group) myworld.find (Pogoroo);
Tcams = (Group) myworld.find (CAMERA);
Acroo = (Group) myworld.find (TRANSFORM);
Animroo = (Animationcontroller) myworld.find (ROO);
Get the length of the animation
Animationtrack track = acroo.getanimationtrack (0);
animlength = 1000; Default length, 1 seconds
if (track!= null) {
Keyframesequence KS = Track.getkeyframesequence ();
if (KS!= null)
Animlength = Ks.getduration ();
}
}
catch (Exception e) {
E.printstacktrace ();
}
}
public void Pauseapp () {}
public void Destroyapp (Boolean unconditional) throws midletstatechangeexception{
Myrefreshtimer.cancel ();
Myrefreshtimer = null;
Myrefreshtask = null;
}
public void Paint (Graphics g) {
if (G.getclipwidth ()!= Viewport_width | |
G.getclipheight ()!= Viewport_height | |
G.GETCLIPX ()!= viewport_x | |
G.getclipy ()!= viewport_y) {
G.setcolor (0x00);
G.fillrect (0, 0, mycanvas.getwidth (), Mycanvas.getheight ());
}
if ((Mygraphics3d!= null) && (myworld!= null)) {
Mygraphics3d.bindtarget (g);
Mygraphics3d.setviewport (viewport_x, Viewport_y,
Viewport_width, Viewport_height);
Mygraphics3d.render (MyWorld);
Mygraphics3d.releasetarget ();
}
}
public void Commandaction (Command cmd, displayable disp)
{
if (cmd = = Exitcommand) {
try{
Destroyapp (FALSE);
Notifydestroyed ();
}
catch (Exception e) {
E.printstacktrace ();
}
}
}
Private class Refreshtask extends timertask{
public void Run () {
if (MyCanvas!=null && mygraphics3d!= null && myworld!= null{
int starttime = (int) system.currenttimemillis ();
int validity = Myworld.animate (starttime);
Mycanvas.repaint (viewport_x, viewport_y, Viewport_width, viewport_height);
}
}
}
Class Examplecanvas extends canvas{
Example3d Myroomidlet;
int i = 0;
Examplecanvas (Example3d testlet) {myroomidlet = Testlet;}
void init () {}
void Destroy () {}
protected void Paint (Graphics g) {myroomidlet.paint (g);}
protected void keypressed (int i) {}
protected void keyreleased (int i) {}
protected void keyrepeated (int i) {}
protected void pointerdragged (int x, int y) {}
protected void pointerpressed (int x, int y) {}
protected void pointerreleased (int x, int y) {}
}
}
Ix. routines running in the simulator
Figure 1 shows the results of the routine running in the WTK emulator. The Kangaroo and the field in the picture look great. If the designer chooses to change any of these objects, it can be done with the The3d tool, and no change is required in the routine MIDlet.
Figure 1 The result of a routine running in the emulator
10. Conclusion
Now you see a more advanced way to create a 3D application using JSR 184, also known as the mobile 3D API. In retention mode, designers can use existing 3D modeling tools to create 3D worlds and objects in them, and then output these models to m3g files. After that, the application simply loads the model and draws a view of the 3D world on the screen.