Google Groups Subscribe to Avatar_J2ME
Email:
Browse Archives at groups.google.com


I love Firefox!
For better performance & secure browsing.


Friday, December 02, 2005

M3G - 3D Object Materials

Materials

A light can cause different effects. A shiny silver ball reflects the light in a different way than a sheet of paper does. M3G models these material characteristics with the following attributes:

  • Ambient reflection: The light that is reflected by an ambient light source.
  • Diffuse reflection: The reflected light is scattered equally in all directions.
  • Emissive light: An object can send out light to imitate glowing objects.
  • Specular reflection: The light that reflects off objects with a shiny surface.

You can set a color for each material attribute. The shiny silver ball's diffused color would be silver and its specular component white. To get the final object color, the material's color mixes with the light's color. If you point a blue light toward the silver ball, it would turn bluish.

Listing 9 shows how to use materials:




Listing 9. Setting a material
// Create appearance and the material.
_cubeAppearance = new Appearance();
_colorTarget = COLOR_DEFAULT;
setMaterial(_cubeAppearance, _colorTarget);

/**
* Sets the material according to the given target.
*
* @param appearance appearance to be modified.
* @param colorTarget target color.
*/
protected void setMaterial(Appearance appearance, int colorTarget)
{
Material material = new Material();

switch (colorTarget)
{
case COLOR_DEFAULT:
break;

case COLOR_AMBIENT:
material.setColor(Material.AMBIENT, 0x00FF0000);
break;


case COLOR_DIFFUSE:
material.setColor(Material.DIFFUSE, 0x00FF0000);
break;

case COLOR_EMISSIVE:
material.setColor(Material.EMISSIVE, 0x00FF0000);
break;

case COLOR_SPECULAR:

material.setColor(Material.SPECULAR, 0x00FF0000);
material.setShininess(2);
break;

// no default
}

appearance.setMaterial(material);
}



setMaterial() creates a new Material object and sets the colors with setColor() using the respective color component identifier. The Material object is then assigned to an Appearance object, which is used in the call to Graphics3D.render(). Although not shown here, you can use Material.setVertexColorTrackingEnable() in order to use the vertex colors for ambient and diffuse reflection instead of using Material.setColor(). Both lights and materials are implemented in LightingMaterialsSample.java. Using keys, you can combine different lights with materials to experiment with the effects.

In Figure 9, the different material characteristics are displayed using an omnidirectional light. Each screenshot sets a single color component to red to demonstrate its effect in isolation.


Figure 9. Different color components: a) Ambient, b) Diffuse, c) Emissive, and d) Specular
Different color components: a) Ambient, b) Diffuse, c) Emissive, and d) Specular

The ambient reflection only reacts to ambient light; thus, using an omnidirectional light has no effect. The diffuse material component creates a matte surface, while the emissive component creates a glowing effect. The specular color component emphasizes the shininess. Again, you could improve the shading quality by using more triangles.

(picked from IBM developer site)

Your first 3D object

Your first 3D object

As a first example, you'll create a cube as displayed in Figure 1.


Figure 1. Sample cube: a) Front view with vertex indices, b) Side view with clipping planes (Front, Side)
Sample cube: (a) front view with vertex indices (b) side view with clipping planes

The cube lives in what M3G defines as a right-handed coordinate system. If you take your right hand and stretch out your thumb, index finger, and middle finger so that each finger is in a right angle to the other two fingers, then the thumb is your x axis, the index finger the y axis, and the middle finger the z axis. Try to align your thumb and index finger with the x and y axis in Figure 1a; your middle finger should then point toward you. I've used eight vertices (the cube's corner points) and placed the cube's center at the coordinate system's origin.

As you can see in Figure 1, the camera that shoots the 3D scene looks toward the negative z axis, facing the cube. The camera's position and properties define what the screen later displays. Figure 1b shows a side view of the same scene so you can easily see what part of the 3D world is visible to the camera. One limiting factor is the viewing angle, which is comparable to using a camera lens: a telephoto lens has a narrower view than a wide-angle lens. The viewing angle thus determines what you can see to the sides. Unlike the real world, 3D computing gives you two more view boundaries: near and far clipping planes. Together, the viewing angle and the clipping planes define what is called the view frustum. Everything inside the view frustum is visible, everything outside is not.

This is all implemented in the VerticesSample class, whose members you can see in Listing 1.




Listing 1. Sample displaying a cube, Part 1: Class members

package m3gsamples1;

import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;


/**
* Sample displaying a cube defined by eight vertices, which are connected
* by triangles.
*
* @author Claus Hoefele
*/
public class VerticesSample extends Canvas implements Sample
{
/** The cube's vertex positions (x, y, z). */
private static final byte[] VERTEX_POSITIONS = {
-1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1,
-1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, -1
};

/** Indices that define how to connect the vertices to build
* triangles. */
private static int[] TRIANGLE_INDICES = {
0, 1, 2, 3, 7, 1, 5, 4, 7, 6, 2, 4, 0, 1
};

/** The cube's vertex data. */
private VertexBuffer _cubeVertexData;

/** The cube's triangles defined as triangle strips. */
private TriangleStripArray _cubeTriangles;

/** Graphics singleton used for rendering. */
private Graphics3D _graphics3d;



VerticesSample inherits from Canvas to be able to draw directly to the display. It also implements Sample, which I defined to help organize this article's different source code samples. VERTEX_POSITIONS defines eight vertices in the same order, as shown in Figure 1a. For example, vertex 0 is defined as position (-1, -1, 1). Remember that I placed the cube's center at the coordinate system's origin; therefore, the cube's edges will be two units long. The camera's position and viewing angle will later define the amount of pixels a unit will occupy on the screen.

The vertex positions are not enough, however; you also have to say what geometry you want to build. Like in a dot-to-dot painting, you have to connect vertices with lines until you see the resulting drawing. M3G poses one restriction though: you must build the geometry from triangles. Triangles are popular with 3D implementations because you can define any polygon as a set of triangles. A triangle is a basic drawing operation on which you can build more abstract operations.

Unfortunately, if you had to describe the cube with triangles alone, you would need 6 sides * 2 triangles * 3 vertices = 36 vertices; this would be a waste of memory as many vertices are duplicated. To reduce memory, you first separate the vertices from their triangle definitions. TRIANGLE_INDICES defines the geometry using the indices of the VERTEX_POSITIONS array and can thus reuse vertices. Next, you reduce the number of indices by using triangle strips instead of triangles. With a triangle strip, new triangles reuse the preceding triangle's last two indices. For example, the triangle strip (0, 1, 2, 3) will translate to two triangles (0, 1, 2) and (1, 2, 3). When you follow the triangle definitions in TRIANGLE_INDICES with Figure 1a, where I marked each corner with the respective index, you'll see that the triangles jump wildly between sides. This is just a pattern to avoid the definition of several strips. I managed with eight vertices and one single triangle strip with 14 indices for the cube.

You use the rest of the class members to draw the cube. Listing 2 shows their initialization.




Listing 2. Sample displaying a cube, Part 2: Initialization
/**
* Called when this sample is displayed.
*/
public void showNotify()
{
init();
}


/**
* Initializes the sample.
*/
protected void init()
{
// Get the singleton for 3D rendering.
_graphics3d = Graphics3D.getInstance();

// Create vertex data.
_cubeVertexData = new VertexBuffer();

VertexArray vertexPositions =
new VertexArray(VERTEX_POSITIONS.length/3, 3, 1);
vertexPositions.set(0, VERTEX_POSITIONS.length/3, VERTEX_POSITIONS);
_cubeVertexData.setPositions(vertexPositions, 1.0f, null);

// Create the triangles that define the cube; the indices point to
// vertices in VERTEX_POSITIONS.
_cubeTriangles = new TriangleStripArray(TRIANGLE_INDICES,
new int[] {TRIANGLE_INDICES.length});

// Create a camera with perspective projection.
Camera camera = new Camera();
float aspect = (float) getWidth() / (float) getHeight();
camera.setPerspective(30.0f, aspect, 1.0f, 1000.0f);
Transform cameraTransform = new Transform();
cameraTransform.postTranslate(0.0f, 0.0f, 10.0f);
_graphics3d.setCamera(camera, cameraTransform);
}



As a first step in init(), you obtain the graphics context for 3D drawing. Graphics3D is a singleton and _graphics3d holds a reference for later use. Next, you create a VertexBuffer to hold the vertex data. As you'll see later, you can assign several kinds of information to a vertex, and VertexBuffer contains all of them. Currently, the only information you need is vertex positions in a VertexArray that is set using _cubeVertexData.setPositions(). The constructor of VertexArray takes the number of vertices (eight), the number of components per vertex (x, y, z), and the size of each component (one byte). Because the cube is so small, one byte is enough to hold one coordinate. You can also create a VertexArray using short values (two bytes) if you want to create larger objects. However, you can't use real numbers, only integers. Next, you initialize a TriangleStripArray with the indices from TRIANGLE_INDICES.

The final part of the initialization code is the camera setup. In setPersective(), you set the viewing angle, the aspect ratio, and the clipping planes. Notice that the aspect ratio and the values for the clipping planes are float values. M3G requires floating point support, which has been available since CLDC 1.1, from the Java Virtual Machine (JVM). After setting the perspective, you move the camera away from the cube so you have a full view of the object. You do this with a translation, a topic I'll explain in more detail in the section about Transformations. For now, trust me that postTranslate() with a positive third parameter moves the camera along the z axis.

After the initialization, you render the scene to the screen. Listing 3 shows this.




Listing 3. Sample displaying a cube, Part 3: Drawing
/**
* Renders the sample on the screen.
*
* @param graphics the graphics object to draw on.
*/
protected void paint(Graphics graphics)
{
_graphics3d.bindTarget(graphics);
_graphics3d.clear(null);
_graphics3d.render(_cubeVertexData, _cubeTriangles,
new Appearance(), null);
_graphics3d.releaseTarget();
}




In paint(), bindTarget() assigns the Canvas's graphics context to Graphics3D. This enables rendering 3D objects until releaseTarget() is called. After a call to clear() erases the background, you draw the cube by using the vertex data and triangles created in init(). Many of Graphics3D's methods throw unchecked exceptions, but I decided to do without a try/catch block because most of the errors are unrecoverable. You can find this sample's complete source code in VerticesSample.java.

To display the sample, I wrote a simple MIDlet. You can get it from the download section together with the article's entire source code. You can see the result of running the sample in Figure 2.


Figure 2. The sample cube
The sample cube

It's difficult to tell that the rectangle on the screen is a cube because I placed the camera directly in front of it, which is like standing too close to a white wall. Why is it white? Because I haven't yet assigned any colors and white is the default. The next section will fix that.

(picked from IBM developer site)

JSR-184 a.k.a. Micro3D a.k.a. Java Mobile 3D

What is Java Mobile 3D?

Definition from
Sony Ericsson developer site:
Java Mobile 3D Graphics (also known as JSR 184) is an API tailored for the generation and presentation of 3D
content on mobile platforms. This section discusses this API and an alternate 3D implementation, HI Corporation’s Mascot Capsule Micro3D version 3 (also known as Micro3D). Sony Ericsson has chosen to implement both API sets, allowing Mascot Capsule Micro3D serve as a migration path for 3D applications until Java Mobile 3D-enabled devices become widely available. Here, we’ll also briefly try to address any possible point of confusion related to the two implementations of 3D Java APIs in Sony Ericsson phones.

M3G is a fun technology to play around for developers, ever in history 3D developement got so easy (well if compared with Direct3D and OpenGL programming)!

Tuesday, November 22, 2005

Content

Installing JDK ...

Firstly, goto "http://java.sun.com" and grab a copy of the latest JDK (notice: only J2RE will only allow you to run java apps, if you are going to developement MUST use a JDK).
Unzip it and put it in a folder, here we use "c:/java/j2sdk" as a default directory!
Then you have to setup an environment variable in order to make work.

Setting up environment variable for Java ...

Right click on "My Computer", select "properties"->"Advanced"->"Environment Variables", and you will see stuff like below:JAVA_HOME=C:\java\jdk1.2.4_01 (refer to path where you install the Java sdk)

PATH= ... ;C:\java\jdk1.2.4_01\bin

Installing J2ME Toolkit ...

This may be as simple as it seems, just goto j2me download site, pick a copy of " Sun Java Wireless Toolkit" ... install it and start coding. Note that you may have a few choice either using an IDE like NetBean, JBuilder, and so on; to the build-in code writing module with the WirelessToolkit that you just downloaded or even start off with a Notepad!

Well my personal favor, a Notepad will do, try compiling with command prompt also, had a better feel of the whole development process.


Testing ...
Kick Start

Six simple Steps for writing a J2ME:
  1. Code a Java file.
  2. Compile with CLDC and MIDP library.
  3. Preverify it with "preverify.exe".
  4. Write a manifest file, then package it with every classes and resources in a JAR file.
  5. Write a JAD file for deploying purposes.
  6. Test it on emulator or real device, do some performance tweaking and fine tuning for portability.

    Some assumption:
  • %J2ME_HOME%=C:\WTK22\
  • %JAVA_HOME%=C:\Program Files\Java\jdk1.5.0_04

Writing a simple CLDC app...
import java.io.*;
import javax.microedition.io.*;

public class TestInputOutput {

public static void main( String[] args ){
try {
String uri ="socket://www.ericgiguere.com:80";
StreamConnection conn = (StreamConnection)
Connector.open( uri );

// Send HTTP request...
PrintStream out = new PrintStream(conn.openOutputStream() );
out.println( "GET /index.html HTTP/0.9\r\n" );
out.flush();

// Get raw HTTP reply...
InputStream in = conn.openInputStream();
int ch;

while( ( ch = in.read() ) != -1 ){
System.out.print( (char) ch );
}

in.close();
out.close();
conn.close();
}
catch( ConnectionNotFoundException e ){
System.out.println( "Socket could not be opened" );
}
catch( IOException e ){
System.out.println( e.toString() );
}
System.exit( 0 );
}
}


Writing a simple MIDP app...
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

public class HelloMIDlet
extends MIDlet
implements CommandListener {
private Form mMainForm;

public HelloMIDlet() {
mMainForm = new Form("HelloMIDlet");
mMainForm.append(new StringItem(null, "Hello, MIDP!"));
mMainForm.addCommand(new Command("Exit", Command.EXIT, 0));
mMainForm.setCommandListener(this);
}

public void startApp() {
Display.getDisplay(this).setCurrent(mMainForm);
}

public void pauseApp() {}

public void destroyApp(boolean unconditional) {}

public void commandAction(Command c, Displayable s) {
notifyDestroyed();
}
}

To Compile your codes:
%JAVA_HOME%\bin\javac -bootclasspath %J2ME_HOME%\lib\midpapi20.jar;%J2ME_HOME%\lib\cldcapi.jar MyJ2MEApp.java

To Preverify your class:
%J2ME_HOME%\bin\preverify.exe -classpath %J2ME_HOME%\lib\midpapi20.jar;%J2ME_HOME%\lib\cldcapi.jar MyJ2MEApp

Writing a Menifest file:
MIDlet-Name: MyJ2MEApp
MIDlet-Version: 1.0.0
MIDlet-Vendor: Avatar

To Package everything:
%JAVA_HOME%\bin\jar cvfm MyJ2MEApp.jar Manifest.mf MyJ2MEApp.class

Writing a Java Application Describtion (JAD) file:
MIDlet-1: MyJ2MEApp, , MyJ2MEApp
MIDlet-Name: MyJ2MEApp
MIDlet-Version: 1.0.0
MIDlet-Vendor: Avatar
MIDlet-Jar-URL: MyJ2MEApp.jar
MIDlet-Jar-Size:
MicroEdition-Profile: MIDP-2.0
MicroEdition-Configuration: CLDC-1.1

*Important notes - remember to fill in the MIDlet-Jar-Size with a correct file size of your jar (e.g.:MIDlet-Jar-Size: 1469)*
To Test your application:
%J2ME_HOME%\bin\emulator.exe -Xdescriptor MyJ2MEApp.jad

Hooray, it is working!!!

Resources:
  1. Tutorial from java.net.
  2. Sample code from sun developer.

JDBC comes to J2ME finally?

J2ME Brief Introduction

J2ME is always comes with limitation, limited memory, limited processing power, limited storage ... . It's made out of MIDP (Mobile Information Device Profile) and CLDC (Connected Limited Device Configuration), CLDC as defined by it's term ... represent a limited resource device. It minimum equiped with 128kb Java memory, 32kb heap, low power and low battery, network/wireless connectivity with low bandwidth. In those days, we can't put too much fancy stuffs in these kind of device, like database for instance.

A big brother of CLDC, the CDC (Connected Device Configuration) had far more capability than it's little brother (minimum 512kb memory, minimum 256kb heap, network persistent connectivity with high bandwidth).

So where do we see CDC and CLDC? CLDC is common among any j2me phones, but CDC can only be seen on high-end PDA phones like Nokia S80 series, Sony Ericsson smart phones and others which compliant with JSR-82.

The JDBC Optional Package

The JDBC optional package has been defined to enable CDC developers to write applications that access relational databases. This package is a subset of the java.sql and javax.sql packages in JDBC 3.0 (it could be JDBC > version 3.0 by the time you read this), with the smaller footprint required by CDC-based applications.

.
. . .
. Note: As of this writing, no reference implementation of the JDBC optional package exists. When an RI is released, you'll be able to build it with the CDC/FP using the OPT_PKGS=jdbc build option of CDC/Foundation or any other CDC-based profile. .
.
.

To support the JDBC optional package, a device must meet the requirements for CDC/Foundation, plus an additional 256KB of RAM and 256KB of ROM.

By Avatar.