This Java tips shows how to create a Swing based 3D book with Java3D.

 import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Paint;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.HashMap;

import javax.media.j3d.Alpha;
import javax.media.j3d.Appearance;
import javax.media.j3d.Background;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.ImageComponent2D;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.RotationInterpolator;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Texture;
import javax.media.j3d.Texture2D;
import javax.media.j3d.TextureAttributes;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.SimpleUniverse;

public class BooksDemo extends JFrame {
  private static final int CANVAS3D_WIDTH = 400;

  private static final int CANVAS3D_HEIGHT = 400;

  private boolean front = true;

  private JPanel xpanel = new JPanel();

  private Canvas3D c3d;

  private RotationInterpolator rotator1;

  private Alpha rotor1Alpha;

  private com.sun.j3d.utils.geometry.Box book;

  private HashMap textures = new HashMap(6);

  public BooksDemo() {
    super("AmazonPick");

    JButton cover1 = UIHelper.createButton("", "cover1_small_button", true);
    cover1.addActionListener(new CoverSwitcher("cover1"));
    JButton cover2 = UIHelper.createButton("", "cover2_small_button", true);
    cover2.addActionListener(new CoverSwitcher("cover2"));
    JButton cover3 = UIHelper.createButton("", "cover3_small_button", true);
    cover3.addActionListener(new CoverSwitcher("cover3"));

    JPanel buttons = new JPanel();
    buttons.add(cover1);
    buttons.add(cover2);
    buttons.add(cover3);
    buttons.setOpaque(false);

    c3d = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
    c3d.setSize(CANVAS3D_WIDTH, CANVAS3D_HEIGHT);

    xpanel.add(c3d);
    xpanel.setOpaque(false);

    this.setContentPane(new GradientPanel());
    this.getContentPane().setLayout(new BorderLayout());
    this.getContentPane().add(xpanel, BorderLayout.CENTER);
    this.getContentPane().add(buttons, BorderLayout.SOUTH);
    this.pack();
    this.setResizable(false);
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    UIHelper.centerOnScreen(this);
  }

  private boolean isBookShowingFront() {
    return front;
  }

  private void rotateBook() {
    if (!isBookShowingFront()) {
      rotator1.setMinimumAngle((float) Math.PI * 1.0f);
      rotator1.setMaximumAngle(0.0f);
    } else {
      rotator1.setMinimumAngle(0.0f);
      rotator1.setMaximumAngle((float) Math.PI * 1.0f);
    }

    front = !front;
    rotor1Alpha.setStartTime(System.currentTimeMillis());
  }

  private class CoverSwitcher implements ActionListener {
    private String coverName;

    CoverSwitcher(String coverName) {
      this.coverName = coverName;
    }

    public void actionPerformed(ActionEvent evt) {
      book.getShape(isBookShowingFront() ? book.BACK : book.FRONT)
          .setAppearance((Appearance) textures.get(coverName));
      rotateBook();
    }
  }

  public void createScene() {
    BufferedImage image = new BufferedImage(xpanel.getWidth(), xpanel
        .getHeight(), BufferedImage.TYPE_INT_RGB);
    getContentPane().paint(image.getGraphics());

    BufferedImage subImage = new BufferedImage(CANVAS3D_WIDTH,
        CANVAS3D_HEIGHT, BufferedImage.TYPE_INT_RGB);
    ((Graphics2D) subImage.getGraphics()).drawImage(image, null, -c3d
        .getX(), -c3d.getY());

    Background bg = new Background(new ImageComponent2D(
        ImageComponent2D.FORMAT_RGB, subImage));
    BoundingSphere bounds = new BoundingSphere();
    bounds.setRadius(100.0);
    bg.setApplicationBounds(bounds);

    BranchGroup objRoot = new BranchGroup();
    objRoot.addChild(bg);

    TransformGroup objTg = new TransformGroup();
    objTg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

    Transform3D yAxis = new Transform3D();
    rotor1Alpha = new Alpha(1, 400);
    rotator1 = new RotationInterpolator(rotor1Alpha, objTg, yAxis,
        (float) Math.PI * 1.0f, (float) Math.PI * 2.0f);
    rotator1.setSchedulingBounds(bounds);

    textures.put("pages_top", createTexture("pages_top.jpg"));
    textures.put("pages", createTexture("amazon.jpg"));
    textures.put("amazon", createTexture("amazon.jpg"));
    textures.put("cover1", createTexture("cover1.jpg"));
    textures.put("cover2", createTexture("cover2.jpg"));
    textures.put("cover3", createTexture("cover3.jpg"));

    book = new com.sun.j3d.utils.geometry.Box(0.5f, 0.7f, 0.15f,
        com.sun.j3d.utils.geometry.Box.GENERATE_TEXTURE_COORDS,
        new Appearance());
    book.getShape(book.TOP).setAppearance(
        (Appearance) textures.get("pages_top"));
    book.getShape(book.RIGHT).setAppearance(
        (Appearance) textures.get("pages"));
    book.getShape(book.LEFT).setAppearance(
        (Appearance) textures.get("amazon"));
    book.getShape(book.FRONT).setAppearance(
        (Appearance) textures.get("cover1"));

    book.getShape(book.BACK).setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
    book.getShape(book.FRONT).setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
    // book.getShape(book.LEFT).setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
    // book.getShape(book.RIGHT).setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);

    objTg.addChild(book);
    objTg.addChild(rotator1);

    Transform3D spin = new Transform3D();
    Transform3D tempspin = new Transform3D();

    spin.rotX(Math.PI / 8.0d);
    tempspin.rotY(Math.PI / 7.0d);
    spin.mul(tempspin);

    TransformGroup objTrans = new TransformGroup(spin);
    objTrans.addChild(objTg);

    objRoot.addChild(objTrans);

    SimpleUniverse u = new SimpleUniverse(c3d);
    u.getViewingPlatform().setNominalViewingTransform();
    u.addBranchGraph(objRoot);

    View view = u.getViewer().getView();
    view.setSceneAntialiasingEnable(true);
  }

  private Appearance createTexture(String fileName) {
    Image sourceImage = UIHelper.readImage(fileName);
    if (sourceImage == null)
      System.out.println("Image could not be loaded from " + fileName);

    TextureLoader loader = new TextureLoader(sourceImage, this);
    ImageComponent2D image = loader.getImage();

    if (image == null)
      System.out.println("Texture could not be loaded from " + fileName);

    Texture2D texture = new Texture2D(Texture.BASE_LEVEL, Texture.RGBA,
        image.getWidth(), image.getHeight());
    texture.setImage(0, image);
    texture.setEnable(true);
    texture.setMagFilter(Texture.BASE_LEVEL_LINEAR);
    texture.setMinFilter(Texture.BASE_LEVEL_LINEAR);

    Appearance appearance = new Appearance();
    PolygonAttributes polyAttributes = new PolygonAttributes(
        PolygonAttributes.POLYGON_FILL, PolygonAttributes.CULL_NONE, 0f);
    appearance.setPolygonAttributes(polyAttributes);
    appearance.setTexture(texture);

    TextureAttributes textureAttributes = new TextureAttributes();
    appearance.setTextureAttributes(textureAttributes);

    return appearance;
  }

  private static class GradientPanel extends JPanel {
    public void paintComponent(Graphics g) {
      super.paintComponent(g);

      if (!isOpaque()) {
        return;
      }

      int width = getWidth();
      int height = getHeight();

      Graphics2D g2 = (Graphics2D) g;

      Paint storedPaint = g2.getPaint();
      g2.setPaint(new GradientPaint(0, 0, Color.WHITE, width, height,
          new Color(200, 200, 200)));
      g2.fillRect(0, 0, width, height);
      g2.setPaint(storedPaint);
    }
  }

  public static void main(String argv[]) {
    final BooksDemo xframe = new BooksDemo();
    xframe.setVisible(true);
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        xframe.createScene();
      }
    });
  }
}

final class UIHelper {
  public static JButton createButton(String text) {
    JButton button = new JButton(text);
    button.setFocusPainted(true);
    button.setBorderPainted(true);
    button.setContentAreaFilled(true);
    return button;
  }

  public static JButton createButton(String text, String icon) {
    return createButton(text, icon, false);
  }

  public static JButton createButton(String text, String icon, boolean flat) {
    ImageIcon iconNormal = readImageIcon(icon + ".png");
    ImageIcon iconHighlight = readImageIcon(icon + "_highlight.png");
    ImageIcon iconPressed = readImageIcon(icon + "_pressed.png");

    JButton button = new JButton(text, iconNormal);
    button.setFocusPainted(!flat);
    button.setBorderPainted(!flat);
    button.setContentAreaFilled(!flat);
    if (iconHighlight != null) {
      button.setRolloverEnabled(true);
      button.setRolloverIcon(iconHighlight);
    }
    if (iconPressed != null)
      button.setPressedIcon(iconPressed);
    return button;
  }

  public static void centerOnScreen(Component component) {
    Dimension paneSize = component.getSize();
    Dimension screenSize = component.getToolkit().getScreenSize();
    component.setLocation((screenSize.width - paneSize.width) / 2,
        (screenSize.height - paneSize.height) / 2);
  }

  public static ImageIcon readImageIcon(String fileName) {
    Image image = readImage(fileName);
    if (image == null)
      return null;

    return new ImageIcon(image);
  }

  public static Image readImage(String fileName) {
    URL url = UIHelper.class.getResource("images/" + fileName);
    if (url == null)
      return null;

    return java.awt.Toolkit.getDefaultToolkit().getImage(url);
  }

}