import java.awt.BorderLayout; import java.awt.Frame; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.media.j3d.Appearance; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.GeometryArray; import javax.media.j3d.PolygonAttributes; import javax.media.j3d.Shape3D; import javax.media.j3d.TriangleArray; import javax.vecmath.Point3f; import javax.vecmath.Vector3f; import com.sun.j3d.utils.universe.SimpleUniverse; @SuppressWarnings("serial") public class CullingTest extends Frame { // ############################# // # modify these to see bug: // ############################# private final boolean ENABLE_BACKFACE_CULLING = true; private final boolean NORMAL_VECTOR_POINTS_IN_POSITIVE_Z = false; // ############################# public class MyTriangleShape extends Shape3D { public MyTriangleShape() { TriangleArray triaArray = new TriangleArray(3, GeometryArray.COORDINATES | GeometryArray.NORMALS); Point3f[] vertices = new Point3f[3]; vertices[0] = new Point3f(0, 0, 0); vertices[1] = new Point3f(1, 0, 0); vertices[2] = new Point3f(0, 1, 0); triaArray.setCoordinates(0,vertices); Vector3f normal = new Vector3f(0, 0, (NORMAL_VECTOR_POINTS_IN_POSITIVE_Z ? 1 : -1)); System.out.println("Normal is: "+normal); System.out.println("Backface culling is: "+ENABLE_BACKFACE_CULLING); triaArray.setNormal(0, normal); triaArray.setNormal(1, normal); triaArray.setNormal(2, normal); this.setGeometry(triaArray); } } public CullingTest() { super("Culling Test"); setLayout(new BorderLayout()); setSize(600, 600); addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { dispose(); System.exit(0); } }); //////////////////////////////////// Canvas3D canvas3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration(), false); add(canvas3D, BorderLayout.CENTER); BranchGroup scene = new BranchGroup(); Shape3D triangle = new MyTriangleShape(); Appearance l_Appearance = new Appearance(); PolygonAttributes l_PolyAttrib = new PolygonAttributes(); l_PolyAttrib.setPolygonMode(PolygonAttributes.POLYGON_FILL); l_PolyAttrib.setCullFace(ENABLE_BACKFACE_CULLING ? PolygonAttributes.CULL_BACK : PolygonAttributes.CULL_NONE); l_Appearance.setPolygonAttributes(l_PolyAttrib); triangle.setAppearance(l_Appearance); scene.addChild(triangle); SimpleUniverse uni = new SimpleUniverse(canvas3D); uni.getViewingPlatform().setNominalViewingTransform(); uni.addBranchGraph(scene); //////////////////////////////////// } public static void main(String[] args) { System.setProperty("sun.awt.noerasebackground", "true"); // needed due to an AWT repaint bug System.out.println("############"); System.out.println("CullingTest"); System.out.println("############"); CullingTest test = new CullingTest(); test.setVisible(true); System.out.println("\n############"); } }