2.4 Putting it together—MyJava3D | JAVA 3D Programming | Chapter 2
2.4 Putting it together—MyJava3D
The MyJava3D example defines the RenderingEngine
interface. This interface defines a simple rendering contract between a client
and a 3D renderer implementation. The RenderingEngine interface defines a
simple renderer that can render 3D geometry described using a Java 3D
GeometryArray. The GeometryArray contains the 3D points and normal vectors for
the 3D model to be rendered.
In addition to adding GeometryArrays to the
RenderingEngine (addGeometry method), the viewpoint of the viewer can be
specified (setViewAngle), the direction of a single light can be specified
(setLightAngle), the scaling factor to be applied to the model can be varied
(setScale), and the size of the rendering screen defined (setScreenSize).
To render all the GeometryArrays added to the
RenderingEngine using the current light, screen, scale, and view parameters,
clients can call the render method, supplying a Graphics object to render into,
along with an optional GeometryUpdater. The GeometryUpdater allows a client to modify
the positions of points or rendering parameters prior to rendering.
From AwtRenderingEngine.java
/**
* Definition of the RenderingEngine interface. A RenderingEngine
* can render 3D geometry (described using a Java 3D GeometryArray)
* into a 2D Graphics context.
*/
public interface RenderingEngine
{
/**
* Add a GeometryArray to the RenderingEngine. All GeometryArrays
* will be rendered.
*/
public void addGeometry( GeometryArray geometryArray );
/**
* Render a single frame into the Graphics.
*/
public void render( Graphics graphics, GeometryUpdater updater );
/**
* Get the current Screen position used by the RenderEngine.
*/
public Vector3d getScreenPosition();
/**
* Get the current View Angle used by the RenderEngine. View
* angles are expressed in degrees.
*/
public Vector3d getViewAngle();
/**
* Set the current View Angle used by the RenderEngine.
*/
public void setViewAngle( Vector3d viewAngle );
/**
* Get the current View Angle used by the RenderEngine. View
* angles are expressed in degrees.
*/
public Vector3d getLightAngle();
/**
* Set the current View Angle used by the RenderEngine.
*/
public void setLightAngle( Vector3d angle );
/**
* Set the Screen size used by the RenderEngine.
*/
public void setScreenSize( int width, int height );
/**
* Set the scale used by the RenderEngine.
*/
public void setScale( double scale );
/**
* Get the scale used by the RenderEngine.
*/
public double getScale();
}
The RenderingEngine interface is implemented by
the AwtRenderingEngine class, which uses simple Graphics rendering calls
(drawPolygon, setColor, drawLine, drawPoint) to render the 3D models.
The RenderingEngine instance is driven by a
RenderingSurface, an instance of a JPanel that provides a Graphics object for
its client area and receives the frames of the rendered scene. The
RenderingSurface extends AnimatingSurface, which creates a rendering thread,
and calls repaint on the JPanel, forcing the scene to be continuously redrawn.
The Surface class, which is the base class for
AnimatingSurface (both taken from Sun Java 2D demos), allows you to specify
Java 2D rendering hints such as RenderingHints.VALUE_ANTIALIAS_OFF, which
switches off antialiasing, and RenderingHints.VALUE_RENDER_SPEED, which tells
the Graphics object to optimize for speed rather than rendering quality. It is
interesting to see the effect of switching on antialiasing (figure 2.4 is on,
figure 2.7 is off), as rendering APIs or 3D graphics hardware does not commonly
support this functionality.
Figure 2.7 MyJava3D rendering with Java2D antialiasing enabled
|
The RotatingGeometryUpdater class is used to
increase the X−angle of the viewer after each subsequent frame.
From RotatingGeometryUpdater.java
/**
* Implementation of the GeometryUpdater interface
* that rotates the scene by changing the viewer position
* and the scale factor for the model.
*/
public class RotatingGeometryUpdater implements GeometryUpdater
{
long lastFrame = −1;
public RotatingGeometryUpdater ( )
{
}
public boolean update( Graphics graphics, RenderingEngine engine,
GeometryArray geometry, int index, long frameNumber )
{
if ( lastFrame != frameNumber )
{
lastFrame = frameNumber;
Vector3d viewAngle = engine.getViewAngle( );
viewAngle.x += 1;
engine.setViewAngle( viewAngle );
}
return false;
}
}
The MyJava3D class pulls all of these elements
together. It creates an AwtRenderingEngine instance, loads a GeometryArray from
disk using a Java 3D ObjectFile object loader, adds the GeometryArray to the
AwtRenderingEngine, constructs a RenderingSurface supplying a
RotatingGeometryUpdater, starts the RenderingSurface, and then adds it to the
content pane of the JFrame that hosts the application.
From MyJava3D.java
/**
* Render a 3D shape using a 3D rendering engine
* that was written from scratch using AWT for
* graphics operations.
*/
public class MyJava3D extends JFrame
{
private static int m_kWidth = 400;
private static int m_kHeight = 400;
private RenderingEngine renderingEngine = new AwtRenderingEngine();
private GeometryUpdater geometryUpdater = new RotatingGeometryUpdater();
private RenderingSurface renderingSurface;
public MyJava3D( )
{
// load the object file
Scene scene = null;
Shape3D shape = null;
// read in the geometry information from the data file
ObjectFile objFileloader = new ObjectFile( ObjectFile.RESIZE );
try
{
scene = objFileloader.load( "hand1.obj" );
}
catch ( Exception e )
{
scene = null;
System.err.println( e );
}
if( scene == null )
System.exit( 1 );
// retrieve the Shape3D object from the scene
BranchGroup branchGroup = scene.getSceneGroup( );
shape = (Shape3D) branchGroup.getChild( 0 );
// add the geometry to the rendering engine...
renderingEngine.addGeometry( (GeometryArray) shape.getGeometry() );
// create a rendering surface and bind the rendering engine
renderingSurface = new RenderingSurface( renderingEngine,
geometryUpdater );
// start the rendering surface and add it to the content panel
renderingSurface.start();
getContentPane().add( renderingSurface );
// disable automatic close support for Swing frame.
setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE );
// add the window listener
addWindowListener(
new WindowAdapter()
{
// handle the system exit window message
public void windowClosing( WindowEvent e )
{
System.exit( 0 );
}
}
);
}
public static void main( String[] args )
{
MyJava3D myJava3D = new MyJava3D();
myJava3D.setTitle( "MyJava3D" );
myJava3D.setSize( 300, 300 );
myJava3D.setVisible( true );
}
}
Comments
Post a Comment