Will Perone

Rendering in 3d on a J2ME phone can be easier than it would seem. This example draws a rotating colored cube with backface culling in about 40 lines of code. The following code requires CLDC 1.1 (although if you convert the doubles to fixed point and use a sin/cos table it will be compatible with CLDC 1.0) and MIDP 2 to run. First we need a couple helper functions, one to multiply matrices and another to draw a face of the cube.
double xr= 0, yr= 0, zr= 0;
private double[] mulmat(double []m1, double[] m2) {
	return new double [] {
		   m1[0]*m2[0] + m1[1]*m2[3] + m1[2]*m2[6],
		   m1[0]*m2[1] + m1[1]*m2[4] + m1[2]*m2[7],
		   m1[0]*m2[2] + m1[1]*m2[5] + m1[2]*m2[8],                
		   m1[3]*m2[0] + m1[4]*m2[3] + m1[5]*m2[6],
		   m1[3]*m2[1] + m1[4]*m2[4] + m1[5]*m2[7],
		   m1[3]*m2[2] + m1[4]*m2[5] + m1[5]*m2[8],                
		   m1[6]*m2[0] + m1[7]*m2[3] + m1[8]*m2[6],
		   m1[6]*m2[1] + m1[7]*m2[4] + m1[8]*m2[7],
		   m1[6]*m2[2] + m1[7]*m2[5] + m1[8]*m2[8]};        
}        
private void face(Graphics g, double[] v1, double[] v2, double[] v3, double[] v4) {
	// if the z portion of the cross product < 0 then it's facing away, don't draw it
	if ((v3[0]-v1[0])*(v2[1]-v1[1]) >= (v3[1]-v1[1])*(v2[0]-v1[0])) return;
	g.fillTriangle((int)v1[0],(int)v1[1], (int)v2[0],(int)v2[1], (int)v3[0],(int)v3[1]);
	g.fillTriangle((int)v2[0],(int)v2[1], (int)v3[0],(int)v3[1], (int)v4[0],(int)v4[1]);
}

In your paint function just do the following to draw the cube in the middle of the screen. The projection is orthographic so in a lot of instances we can just drop the z calculations:
double c= Math.cos(xr), s= Math.sin(xr), x,y,z;
double[] rx= {1,0,0, 0,c,-s, 0,s,c};
c= Math.cos(yr); s= Math.sin(yr);
double[] ry= {c,0,s, 0,1,0, -s,0,c};
c= Math.cos(zr); s= Math.sin(zr);
double[] rz= {c,-s,0, s,c,0, 0,0,1};        
double []r= mulmat(mulmat(rx, ry), rz);
double v[][]= { {-1,-1,-1}, {1,-1,-1}, {-1,1,-1}, {1,1,-1}, // back
               {-1,-1,1}, {1,-1,1}, {-1,1,1}, {1,1,1} }; // front
int sx= screenwidth>>1, sy= screenheight>>1;
final double size= 20;
for (int i= 0; i < v.length; i++) {
	x= v[i][0]; y=v[i][1]; z= v[i][2];
	v[i][0]= (r[0]*x + r[1]*y + r[2]*z)*size + sx;
	v[i][1]= (r[3]*x + r[4]*y + r[5]*z)*size + sy;
	// Z is not used to render (orthographic) so don't calculate it       
}
g.setColor(0x00ff00); face(g, v[1],v[0],v[3],v[2]);// back
g.setColor(0xff0000); face(g, v[4],v[5],v[6],v[7]);// front
g.setColor(0x0000ff); face(g, v[0],v[1],v[4],v[5]);// top
g.setColor(0xff00ff); face(g, v[3],v[2],v[7],v[6]);// bottom
g.setColor(0xffff00); face(g, v[0],v[4],v[2],v[6]);// left
g.setColor(0x00ffff); face(g, v[5],v[1],v[7],v[3]);// right
xr+=0.05; yr+=0.1; zr+=0.06; // make it spin around


3 Comments
Jared (http://hpalace.com) 1 1
Old sk00l software 3d rendering.
bao 1 1
good 4d render
bao 0 0
my bad, 3d not 4d

<- for private contact