import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.image.*;
import java.awt.image.*;

public class Immediate extends Applet implements Runnable{
        final boolean immediate = true;
        final int textureMode =
                TextureAttributes.BLEND;
                //TextureAttributes.MODULATE;
                //TextureAttributes.DECAL;
        final boolean silentCrash = false;

        Transform3D T = new Transform3D();
        double theta = 0;
        Canvas3D canvas;
        GraphicsContext3D gc;
        ColorCube cube;
        Sphere sphere;
        Shape3D sphereShape;
        PointLight pl;

        public void render() {
                gc.clear();
                T.set( new Vector3d( -0.3, 0, 0 ) );
                gc.setModelTransform(T);
                gc.draw(cube);
                theta += 0.1;
                T.rotY( theta );
                T.setTranslation( new Vector3d( 0.3, 0, 0 ) );
                gc.setModelTransform(T);
                gc.draw(sphereShape);
                canvas.swap();
        }
        public void run() {
                while (true) {
                        if( pl == null ){
                                pl = new PointLight();
                                pl.setPosition( 0, 0, 10 );
                                gc.addLight( pl );
                        }
                        render();
                        Thread.yield();
                }
        }
        public Immediate() {
                setLayout(new BorderLayout());
                canvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
                add("Center", canvas);

                SimpleUniverse u = new SimpleUniverse(canvas);
                u.getViewingPlatform().setNominalViewingTransform();
                gc = canvas.getGraphicsContext3D();

                Appearance app = new Appearance();
                app.setMaterial( new Material() );

                BufferedImage bi = new BufferedImage( 1, 1, BufferedImage.TYPE_INT_RGB );
                Graphics g = bi.getGraphics();
                g.setColor( Color.pink );
                g.fillRect( 0, 0, 1, 1 );
                ImageComponent2D im2D = new ImageComponent2D( ImageComponent.FORMAT_RGB, bi );
                Texture2D tex = new Texture2D( Texture.BASE_LEVEL, Texture.RGB, 1, 1 );
                tex.setImage( 0, im2D );
                app.setTexture( tex );

                final TextureAttributes ta = new TextureAttributes();
                ta.setCapability( ta.ALLOW_MODE_WRITE );
                ta.setTextureMode( textureMode );
                app.setTextureAttributes( ta );

                cube = new ColorCube(0.25);
                sphere = new Sphere(0.25f, Primitive.GENERATE_NORMALS | Primitive.GENERATE_TEXTURE_COORDS, app);
                sphereShape = sphere.getShape();

                final Choice choice = new Choice();
                choice.addItemListener( new ItemListener(){
                        public void itemStateChanged( ItemEvent e ){
                                String s = choice.getSelectedItem();
                                if( s.equals( "BLEND" ) ){
                                        ta.setTextureMode( ta.BLEND );
                                }else if( s.equals( "MODULATE" ) ){
                                        ta.setTextureMode( ta.MODULATE );
                                }else if( s.equals( "DECAL" ) ){
                                        ta.setTextureMode( ta.DECAL );
                                }
                        }
                });
                choice.addItem( "BLEND" );
                choice.addItem( "MODULATE" );
                choice.addItem( "DECAL" );
                add( "North", choice );

                if( immediate ){
                        canvas.stopRenderer();
                        if( silentCrash ){
                                pl = new PointLight();
                                pl.setPosition( 10, 0, 10 );
                                gc.addLight( pl );
                        }
                        new Thread(this).start();
                }else{
                        BranchGroup BG = new BranchGroup();
                        BG.addChild( sphere );
                        PointLight pl = new PointLight();
                        pl.setPosition( 0, 0, 10 );
                        pl.setInfluencingBounds( new BoundingSphere() );
                        BG.addChild( pl );
                        u.addBranchGraph( BG );
                }
        }
        public static void main(String[] args) {
                new MainFrame(new Immediate(), 256, 256);
        }
}
