The AWTGLRenderer doesn't really draw anything when you are calling draw(), but it enqueues the calls to be executed in the AWT event thread dispatch instead (i.e. in the AWTGLCanvas' paint()-method). Your code works, you just don't get any repaint events for the applet, which is why nothing moves. Maybe it's not possible in all cases to schedule a repaint() from inside paint()...i'm not sure. However, i've modified your applet slightly to start an additional thread that just makes the applet repaint itself, i.e. execute your drawing code.
Personally, i wouldn't do it that way, but make my own thread that does the calculations and leave the applets paint() alone. That way, you'll benefit from a feature of the AWTGLRenderer: It runs multithreaded, i.e. calculations in one thread, drawing in another (in the AWT event dispatch thread in this case). In your code, both operations happen in the AWT EDT. I haven't modified your code to work that way (i.e. move the code from paint into that thread's loop), because it requires some more work: Your mouse listeners are modifying jPCT objects directly, but jPCT isn't thread save, i.e. you shouldn't modify a jPCT object from another thread than the rendering thread. Instead, the listeners should just flag what they want to do and let the calculation thread execute the operations. Anyway, here's the modified example:
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.InputStream;
import javax.swing.JApplet;
import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.IRenderer;
import com.threed.jpct.Lights;
import com.threed.jpct.Loader;
import com.threed.jpct.Matrix;
import com.threed.jpct.Object3D;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.World;
import java.lang.System;
public class jPCTGears extends JApplet implements MouseListener, MouseMotionListener, Runnable
{
private Object3D redGear, greenGear, blueGear, assemblyPivot;
private FrameBuffer buffer = null;
private World world = null;
private Camera camera = null;
private int width = 640;
private int height = 480;
private float gear_rotation = 0.02f;
private int prevMouseX, prevMouseY;
private boolean loop=true;
Canvas myCanvas;
// Initialize all components of the applet
public void init()
{
// sign the applet up to receive mouse messages:
world = new World(); // create a new world
World.setDefaultThread( Thread.currentThread() );
// create a new buffer to draw on:
buffer = new FrameBuffer( width, height, FrameBuffer.SAMPLINGMODE_HARDWARE_ONLY );
buffer.disableRenderer( IRenderer.RENDERER_SOFTWARE );
myCanvas = buffer.enableGLCanvasRenderer();
add( myCanvas, BorderLayout.CENTER);
myCanvas.setVisible( true );
// load some 3D objects and make sure they have the correct orientation:
redGear = loadMeshFile( "RedGear.3ds" );
redGear.rotateY( (float)Math.PI / 2.0f );
redGear.rotateMesh();
redGear.setRotationMatrix( new Matrix() );
redGear.setOrigin( new SimpleVector( 0, 0, 0 ) );
redGear.build();
greenGear = loadMeshFile( "GreenGear.3ds" );
greenGear.rotateY( (float)Math.PI / 2.0f );
greenGear.rotateZ( 0.35f );
greenGear.rotateMesh();
greenGear.setRotationMatrix( new Matrix() );
greenGear.setOrigin( new SimpleVector( -145.0f, 0, 0 ) );
greenGear.build();
blueGear = loadMeshFile( "BlueGear.3ds" );
blueGear.rotateY( (float)Math.PI / 2.0f );
//blueGear.rotateZ( 0.40f );
blueGear.rotateMesh();
blueGear.setRotationMatrix( new Matrix() );
blueGear.setOrigin( new SimpleVector( 0, -140.0f, 0 ) );
blueGear.build();
// Set up a pivot point for the entire gear assembly:
assemblyPivot = Object3D.createDummyObj();
assemblyPivot.setOrigin( new SimpleVector( 0, 0, 0 ) );
// Make the gears children to assemblyPivot.
// Translations and rotations to assemblyPivot
// will affect the entire gear assembly:
assemblyPivot.addChild( redGear );
assemblyPivot.addChild( greenGear );
assemblyPivot.addChild( blueGear );
// add the objects our world:
world.addObject( redGear );
world.addObject( greenGear );
world.addObject( blueGear );
world.buildAllObjects();
lookAt( redGear ); // make sure the camera is facing towards the object
letThereBeLight(); // create light sources for the scene
myCanvas.addMouseListener( this );
myCanvas.addMouseMotionListener( this );
new Thread(this).start();
}
// Draw the scene
public void paint( Graphics g )
{
redGear.rotateAxis( redGear.getZAxis(), -gear_rotation );
greenGear.rotateAxis( greenGear.getZAxis(), 2.0f * gear_rotation );
blueGear.rotateAxis( blueGear.getZAxis(), 2.0f * gear_rotation );
buffer.clear(); // erase the previous frame
// render the world onto the buffer:
world.renderScene( buffer );
world.draw( buffer );
buffer.update();
buffer.displayGLOnly();
myCanvas.repaint();
}
public void destroy() {
loop=false;
}
public void run() {
while (loop) {
this.repaint();
try {
Thread.sleep(10);
} catch(Exception e) {
//Don't care...
}
}
}
// Load a 3Ds file, and return its Object3D handle
public Object3D loadMeshFile( String filename )
{
Object3D newObject;
//Object3D[] objs = Loader.load3DS( myURL, "models" + "/" + filename, 1.0f );
Object3D[] objs = Loader.load3DS( getResource( filename ), 1.0f );
if( objs.length==1 )
{
// The object loaded fine, just need to initialize it
newObject=objs[0];
newObject.setCulling( Object3D.CULLING_DISABLED );
newObject.build();
}
else
{
// Didn't load anything, or loaded
// more than 1 object (not supposed to happen)
System.out.println( "Unknown file format: " + filename );
newObject = null;
}
return newObject;
}
private InputStream getResource( String resourceName )
{
return getClass().getClassLoader().getResourceAsStream( resourceName );
}
// point the camera toward the given object
private void lookAt( Object3D obj )
{
camera = world.getCamera(); // grab a handle to the camera
camera.setPosition( 0, 0, 500 ); // set its *relative* position
camera.lookAt( obj.getTransformedCenter() ); // look toward the object
}
// create light sources for the scene
private void letThereBeLight()
{
world.getLights().setOverbrightLighting (
Lights.OVERBRIGHT_LIGHTING_DISABLED );
world.getLights().setRGBScale( Lights.RGB_SCALE_2X );
// Set the overall brightness of the world:
world.setAmbientLight( 50, 50, 50 );
// Create a main light-source:
world.addLight( new SimpleVector( 50, -50, 300 ), 20, 20, 20 );
}
// Dragging the mouse should rotate the entire gear assembly
public void mouseDragged( MouseEvent e )
{
// get the mouse's coordinates:
int x = e.getX();
int y = e.getY();
Dimension size = e.getComponent().getSize();
// Calculate the angles to rotate the assembly:
float thetaY = (float)Math.PI * ( (float)(x-prevMouseX)/(float)size.width );
float thetaX = (float)Math.PI * ( (float)(prevMouseY-y)/(float)size.height );
// Apply the rotations to the gear assembly:
assemblyPivot.rotateAxis( assemblyPivot.getXAxis(), thetaX );
assemblyPivot.rotateAxis( assemblyPivot.getYAxis(), thetaY );
// Keep track of the mouse location:
prevMouseX = x;
prevMouseY = y;
}
public void mousePressed( MouseEvent e )
{
// Start keeping track of the mouse location now.
// This prevent the gear assembly from jerking to the new angle
// whenever mouseDragged first gets called:
prevMouseX = e.getX();
prevMouseY = e.getY();
}
public void mouseReleased( MouseEvent e ){}
public void mouseEntered( MouseEvent e ) {}
public void mouseExited( MouseEvent e ) {}
public void mouseClicked( MouseEvent e ) {}
public void mouseMoved( MouseEvent e ) {}
}