Børre Stenseth
OpenGL>Pipeline>Applet

A 3D Applet

What
Applet failed to run. No Java plug-in was found.
a handmade simple 3D applet

The purpose is not to make a complete 3D-package or to compete with existing 3D applets like Anfy [1] or Shout3D [2] . The purpose is to make something very simple ands extensible.

The 3D modeling is implemented in a class gob, with 3 inner classes: p3D, matrise and polygon. A gob-object is set up to work with a component-object in Java. This means that an applet can contain other things than the area where the 3D action takes place. There may be more than active gob-object in an Applet.

gob use the usual 2D-methods in Java when rendering.

gob

The Applet is implemented in class gob

_gob.java

Methods

Methods in gob are:

  • gob(Component comp)
    Sets up a gob-object against a component. Sets default values for polygon color and background color. Sets projection to parallel projection and viewport like the components dimensions.
  • clearAll()
    Clears the model matrix and removes list of polygons to render.
  • drawBox(float dx, float dy, float dz, int mode)
    helper to draw a bok with sides dx,dy og dz, with origo in centrum. mode may have values gob.FILL or gob.FRAME.
  • flush()
    Render all polygons to screen.
  • pBegin(int mode)
    Establish a polygon and prepares for receiving corners. mode may have values gob.FILL or gob.FRAME.
  • pEnd()
    Ends a polygon.
  • popMatrix()
    Pop last pushed matrix from the stack and use it as model matrix.
  • pushMatrix()
    Push model matrix to the stack
  • rotateX(float v)
    Rotate v radians around x-axis.
  • rotateY(float v)
    Rotate v radians around y-axis.
  • rotateZ(float v)
    Rotate v radians around z-axis.
  • scale(float sx,float sy,float sz)
    Scaling with factors sx, sy, sz, relative to origo.
  • translate(float tx,float ty,float tz)
    translates tx, ty, tz.
  • setBackground(Color c)
    Set background color
  • setImage(Image im)
    put an image in background, anchored at upper left in viewport
  • setColor(Color c)
    sets current rendering color.
  • setIdentityMatrix()
    Set modelmatrix to identity matrix
  • setOrtho(float xl, float yt, float dx, float dy)
    Paralell projection to i xy-plane. The part limited by parameters are mapped to viewport Den delen av xy-planet som er
  • setPerspective(float xv, float yv)
    Sets projection to perspective, giving the "lens". xv og yv oppgis given in degrees, looking from origo down z. No clipping
  • setViewport(float xl,float yt,float w, float h)
    Where to map the projection. parameters relative to gob-objects component.
  • vertex(float x, float y, float z)
    One vertex.

Light

There is only one light source. This light supplies diffuse light along negative z. Since the eye is placed in origo, looking down z, the light appears as a "headlight". The light is white.

A better light model might be a sensible extension

Hidden surfaces

The list of polygons are sorted according to the point with longest distance from the eye, and the list is rendered accordingly. With the simple eye-model we have, the negative z-value is the distance from the eye.

This is a simplified version of Painters algorithm.

This depth sorting is not waterproof, but it works for most convex, closed forms.

A better surface depth-sorting might be a sensible extension

Clipping

There is no clipping in gob. The only clipping that goes on is when the projected image is mapped to the viewport. Viewport is clipped by java.awt.

Projection

There are two alternative projections: parallel (setOrtho) and perspective (setPerspective).

The parallel projection is strait forward: The z-coordinates is removed and we are left with 2D-polygon which ia mapped from model to viewport.

The perspective projection is a little more complicated. The distance from the eye must be taken into consideration.

perspec

We decide to project onto a plane with a distance from the eye, and we decide that the projection plane has dimension 1 x 1.
We want to find Q.

We set up the following equations:

  • tg(Vx)=0.5/d
  • P.x/P.z=Q.x/d.

We eliminate d and gets Q.x=(P.x*0.5)/(tg(Vx)*P.z). We can do the same operation for y.

Then we are ready to map the square (-0.5,-0.5) - (0.5,0.5) to viewport.

Viewport

Viewport can either be set to cover the component that gob is attached to, or we can specify viewport as a part of this component. The latter solution is chosen. It gives us greater freedom to design the component.

Double Buffering

The method flush render all polygons to a background buffer, and then copy this background buffer to the component gob is attached to


//Image Buffer..  
..
Graphics tmpg=Buffer.getGraphics();
tmpg.setColor(BKColor);
// fill background
tmpg.fillRect(< viewport>);
// possible background image
if(theImage!=null)
  tmpg.drawImage(< viewports uppeleft>,BKColor, null);

// polygons in list
for(int ix=0;ix< drawList.size();ix++)
 ((polygon)drawList.elementAt(ix)).render(tmpg);

// copy to viewport
g.clipRect(< viewport>);
g.drawImage(Buffer,0,0,null);

Note that we avoid flickering by implementing:

public void update(Graphics g)
{
  paint(g);
}

This shortcuts the blanking that awt initiates.

Boxes

It is up to you how you organize the use of gob. A typical applet is the applet that runs on the top of this page. Source:

_a3dboxes.java

Falling

Applet failed to run. No Java plug-in was found.

A simple demo of gob. Falling boxes.

  void drawFallingBoxes()
  {
    // a demo with some falling boxes
    hb.setBackground(new Color(1.0f,1.0f,1.0f));
    // use default viewport and ortho, full applet

    // boxes are "falling" in the direction of pos y
    hb.translate(FALLWIDTH/2.0f+3.0f,0.0f,0.0f);
    for(int ix=0;ix< BOX_COUNT;ix++)
    {
      boxpos[ix]+=FALLSTEP;
      if(boxpos[ix] > FALLHEIGHT)
      boxpos[ix]-=FALLHEIGHT;

      hb.pushMatrix();
      hb.translate(0.0f,boxpos[ix],0.0f);
      if(ix%2==0)
        hb.rotateZ(vz);
      else
        hb.rotateZ(-2*vz);
      if(ix%3==0)
        hb.rotateX(vx);
      else
        hb.rotateX(-vx);
      if(ix%2==0)
        hb.rotateY(2*vy);
      else
        hb.rotateY(vy);

      hb.setColor(boxcolor[ix]);
      hb.drawBox(BOX_SIDE,BOX_SIDE,BOX_SIDE,gob.FILL);
      hb.popMatrix();
  }

Rotations vx,vy,vz is updated in the Applets run method.

Stop it with right-click, change rotation with left-drag.

Full source:

_a3dfalling.java

Runner

Applet failed to run. No Java plug-in was found.

Source:

_a3dwalker.java

Movie

Applet failed to run. No Java plug-in was found.

The Applet combines the 3d-robot, theMan, from Applet "Runner" with a scrolling of images. The Applet takes the following parameters:

  • piccount value=2
  • picext value="jpg"
  • sleep value=20
  • imagepath value="images"

which means it takes two jpg-images in folder images. The Applet updates the background each 20 milliseconds. The two images are very simle:

img0001 img0002

A better solution will of course be to construct a complete surrounding scene.

Source:

_a3dmovie.java

Football

A form with 20 hexagons and 12 pentagons. The Buckball is explained in Ball.

Applet failed to run. No Java plug-in was found.

Source: https://svn.hiof.no/svn/webnew/sites/j3d/gobApplets/src/a3dbucky.java

Source:

_a3dbucky.java

Logo

This sample reveals shortcomings of the solution for depth sorting of surfaces. We also see that we do not smooth the transition from one surface to another.

Why not improve it ?

Source:

_a3dlogo.java
References
  1. Anfy, 3D Appletwww.anfyteam.com/anj/index.html24-05-2009
  1. shout3d, 3D Appletshout3d.net/24-05-2009
Maintainance
Modified May 2009, B Stenseth
(Welcome) OpenGL>Pipeline>Applet (Frames)