4D object viewer in wireframe 3D - Java (rotating 4D objects, viewing in stereo 3d)


An R4 (4D) rotation and viewing program with some 4D objects, written in Java 1.6.0 (6.0). requires stereo 3D red/blue glasses, or LCD shutter glasses (you must put in the SW support/interfaces, we don't have one). It is under the GPL3 license.
This program rotates 4d objects about the 6 planes, xy, xz, xw, yz, yw, zw and has sliders for each, and projects the objects into 3D-space for viewing. The extra slider, dw, is for camera position or distance from the object. if you get too close you will be inside and it will operate funny. You will require red/blue 3d glasses that you can get at the comic book store, and preferably a high-resolution monitor - anything 1024x768 ot better is good, because there are are a lot of lines to sort out in some objects. wireframe 3D is not a great way to view objects with 120 cells or more. If you want more 4D objects, more can probably be converted from Stella4D. Stella4D is a pretty nice program ($80?).

If you don't have Java installed, you will also need to install the JRE to run the app.
If you with to recompile it or change the program, all you need (to tweak the constants), is to get the Java 1.5 (5.0) or better SE JDK. Currently Java consumes 32-38MB while running.

This project has grown beyond my ability to maintain it. If you can work with the source, please run with it (and tell me about it - I would like to hear that this actually went farther.

gen4D.zip generates a hypersphere, tiger, and duocylinder. Dated Aug 7, 2007.

Mac & UNIX Users: This should read the .4D files. If there are problems, email me. I am now using java.util.Scanner for reading files and it ignores whitespace (including linefeeds & carriage returns).

The current version contains about 3279 lines of code.
If you want to try your hand at viewing without 3d glasses:
set the screen color constants to Color(255,255,255) (white) in ColorScheme.java
set EYESHIFT back to largest/50.0 in Hyper3.java
recompile the code with javac -target 1.5 *.java then jar cvfe Hyper3.jar Hyper3 *.class *.java, rerun it, and cross your eyes a little bit. another trick is to make the window very wide and short. this separates the images enough so that you might be able to cross your eyes better. Just don't do it for a long time.


Download Now
Hyper3-4D-4.3.zip (v4.3, 8/9/2007)

Download Now
Hyper3lcdshutter-4D-4.3.zip LCD shutter glasses support (v4.3, 8/8/2007)

Download Now
gen4D.zip programs to generate 4D objects files (, 8/7/2007)

Download Now
hypersphere.zip 4D objects (, 8/8/2007)

Download Now
hypercube3.zip source code (, 8/8/2007)

The .ZIP file containing the source, jar(executeable) class(executable) and object files can be obtained here. Sorry - previous versions vefore 3.17 were large because 7-zip recurses by default when it archives instead of by the switch (bug). you must make a folder/directory for the program and extract into (if your zip program doesn't do that already for you). if you don't have an unzip program, get 7-zip. it's free.
Create a folder for the .ZIP file. move the .ZIP file (which looks like zipped folder) into the folder you created. then extract the .ZIP file. If you are on Windows Vista or XP, you extract by right clicking on the .ZIP file and picking "Extract All".
To run it, try 1 of these 3 things to start the program (the first is the simplest):

3D glasses

The LCD shutter glasses support is only for homebuilt serial port (RTS) and parallel port (data 2 of 0-7) models and requires non-trivial manual installation (copying 3 files - dev install is more complicated) of RxTx. The beta webstart version does not work on Windows yet. If you have a parallel printer attached the lcd shutter version will send garbage to it. It is only meant for the following old LCD shutter glasses controller circuits:
lcd shutter glasses controllers (old): http://www.tkk.fi/Misc/Electronics/circuits/sega3d.html (serial port switches on RTS)
http://stereo3d.com/3dhome.htm (switches on par port pin 4:data 2[of 0-7])

3D glasses can be purchased online from here in low quantities, and here in high quantities. They can be purchased from other places, just google "3d glasses".


Currently there are some odd dynamics I don't understand yet concerning scaling of the object to fit the window that has to do with dw perspective calculations. I had to knock it down with a hand-picked value because it wasn't fitting the window. this is SCALEDDOWNBY in the program's source code. This dw slider must be increased for some reason when the window size changes. it is this problem which slightly affects printing, which in Java, amounts to 540x720 equivelant pixels for an 8.5"x11" page, which is 100 pixels thinner than the default window size. I haven't nailed down exactly what is causing problems where What You See Isn't Quite What You Get (slightly).


Really old book "Experiments in 4 Dimensions" by Heiserman, published by Tab Books I think. It is a complete and detailed introduction to manipulation in n dimensions.
out of print
(link also contains list of other books which are related to n dimensions)
Title: The Wild World Of 4-manifolds
Author: Alexandru Scorpan
Format: Hardcover, 609 pages
Publication Date: March 2005
Publisher: Amer Mathematical Society
ISBN-10: 0821837494
ISBN-13: 9780821837498
List Price: $69.00

this book *may* give a program for generating polytopes which you can adapt: (subject: Computational Geometry) but the article costs $32.
Title: Mathematical Programming
Publisher: Springer-Verlag

Title: Regular and Semi-Regular Polytopes (I and II)
Author: Coxeter, H.S.M.
Mathematische Zeitschrift (Journal) 46, 380-407, 1940.
ISSN 0025-5874 (Print) 1432-1823 (Online)

Title: Introduction to Geometry
Author: Coxeter, H.S.M.
Publisher: John Wiley & Sons Inc

Title: 4 Dimensional Space
Author: Eckhart, L.
Publisher: Indiana University Press
no longer at this publisher...

Title: The Wild World of 4-Manifolds
Author: Alexandru Scorpan

I have not tried these books yet, but it is a sampling of what can be found on the subject.

generating polytopes: I haven't found any programs yet for generating polytopes except what I have listed here for hyperspheres. if you have one or an algorithm to donate, please do. We need more objects to view.

hypercube (4D cube with 16 vertices), rendered as stereo red-blue 3d image on black background for easy viewing

hypercube Hybercube from older version.

hyperoctagedron, rendered as stereo red-blue 3d image on black background for easy viewing
HYPEROCTAHEDRON.4D — Hyperoctahedron image saved with version 4.3

.4d file format:

First line contains the number of vectors as an integer.
Second line contains the number of vertices (points) as an integer.
A blank line.
The appropriate number of lines of vectors, each line containing 2 integers, the "from" point number (0-based), and the "to" point number (0-based) separated by a space.
A blank line.
The appropriate number of lines of vertices (points), in order, each line containing the point values for X Y Z W separated by a space.
The rest of the file is ignored and can contain comments.


v3.1 Jim Michaels 2/11/2004  (now 2007)
conversion to Java for the nice GUI and easy-looking graphics.  What
a job! awt/swing looks a lot like Tk.  strike that.  page flipping
is now done without waiting for a keypress.  This is my 2nd attempt
to write something in Java, so don't expect much.  It's taken me a
year of trying to figure our how to mesh the gui and the rest of the
code without the proper books. center panel in the border layout is
the drawing area.  east panel has a flow layout which has a controls
panel. the controls panel contains 4 buttons and 7 sliders, 6 for
adjusting the 6 angle increments.  the 7th slider is for distance dw
if wanted.

The 4D object will be rotated about the 6 planes (not axes).  Weird
concept. These 6 rotations will be performed on all the vertices of
the wire-frame object, every time the object is redrawn.  The object
will be rotated over and over again by the amounts you specify. I
verified that I was correctly getting the length of a vector at

load up the reference arrays with the coordinates of a hyperoctagon
The vectors[] array holds a list of line segment indexes.

June 2007 found a way to do page flipping (double-buffering as it's

Many thanks to Jack Marsh and Lew on the newsgroups for putting up
with my Java help requests.

-----------------------------possible new features
- I should add a checkbox for 16:9 (HD) screens that sets xRatio.
- checkbox for "auto-fit".
- option to save gif image...!

removed some dead code, changed SLEEPFOR constant from 100 to 10 for
more realistic speed.
changed the SLEEPFOR constant to 20 for examination purposes.
fixed the initial display spike problem.
fixed the reset button so it works.
the backup is also rescaled during a resize.
the load_object() function was changed so it copied the vertices to
    the backup after a rescale.
updated variable names to reflect their use.
changed xRatio to simply 4.0/3.0 since we are working with windows
rather than full-on displays.
3.5 June 19,2007
added "fit-to-page" printing feature and choice of white or black
print background (for posters).
added "save image" feature.
got menu to work with help of SJM.
3.6 June 21,2007
for Mac and UNIX compatibility, changed file reader in load_object()
    to use java.util.Scanner.
added "Save JPG+PNG" menu item.
a) added class ViewTextFile to bring up a modal JDialog to show the
    file that was read for the object being displayed... for the
    default object this is a noop since there in no file.

b) Modified ControlFrame

   1) removed Save Button.  could easily be added back, but [File]
      menu is the proper place for save

   2) added [Show Source] to [File] menu
      [show source]  modal JDialog to show the file that was read.
       Once this dialog is visible ControlFrame is unreachable. This
       behavior can be modified by changing true to false in the
       JDialog constructor. I made it modal, because of confusion
       that might occur if one object's list is displayed, and then
       a second unrelated object is loaded. I can think of several
       ways to handle this, but making the JDialog modal was easy.

  3) replaced [Save...] JMenuItem with a more powerful version that
       displays all the available formats... jpeg, gif, png, bmp,
       wbmp etc The code is quite compact and is located at the
       bottom of the file. The nice thing about this code is that is
       a new format is added in future, they will show up

 c) Modified Hyper3

    1)  added a couple of lines of code to remember the last file
        loaded.  This is used to provide a default name for Save

    2) modified the JDialog that asked if you want to print on black
       or white background added [ok] JButton, to take action.  I
       found using [x] to activate was completely counterintuitive.
       It was not easy to make the [ok] button sit in a reasonanble
       place.  LOTS of changes.

   3) added filetype as parameter for doWriteImageDialog()
      [file]->[save]->format returns a known Image format/filetype
      and calls this method

   4) call showSaveDialog(...) rather than showOpenDialog(....) for
      [save] operations

   5) modified writeImage()
        added String imageFormat as parameter
       gutted all references to .png and .jpg

 d) things to do
    make ControlFrame sizeY match drawframe.

    the imageFormats occur in both UPPER and lowercase, perhaps
    remove Uppercase Versions

    [ok] in print dialog maybe should be [print]

    no action keys for save

VK_S is the S key, CTRL_MASK means the control key.  this was set in
controlFrame.  was removed. As a replacement I have added a JPopup
Menu  activated by right mouse that brings up a copy of the File
menu contents.... far harder to do than I would have expected.
While doing this I have reorganized ControlFile.java.
      moved Menu creation code to method.
      added label to make2Dslider,  this method now adds label and
            slider into the frame replaced code that adds numeric
            labels to slider with a for loop
      added methods, to copy contents of a JMenu.. this was a bear
      to get right
      added local class from PopupMenuDemo.java from Sun.
      added  slash-splat splat-slash Javadoc comments  to most methods
             generally I find these useful after the code is
             working. they do make things harder to read
             these are basis for the java api documentation

  Removed a debugging output line I left in ViewTextFile
  Made contolframe match initial Ysize of drawframe.  Just looks
  better. And gets rid of extra space created when I removed [save]
fixed save image menu: duplicate items were there.  converted to
  uppercase and made sure only UNIQUE items were left.
added fit-to-window.
sjm added better fit-to-window and fit-to-page code
sjm Cosmetic changes to ControlFrame. Lined up the buttons and put the
    2d sliders in a recessed panel.
sjm Vector2D many methods added.  Needs Javadocs added.
sjm Hyper3 major changes, including consolidation of all scaling and
    drawing.  Also all the dead code removed.
sjm When you print,  the fitToPage checkbox is being ignored.  Instead
    the fitToWindow logical is being used.  That is because fitToWindow
    is being used in the guts of the code a couple of calls down.  The
    fix is to pass the correct logical down the call stack.  Tricky
    because CDrawPanel doesn't and shouldn't care about fitToWindow,  so
    fitToWindow has to be inserted into the call stack inside Hyper3.

sjm new logic to replace overlapped lines with magenta.  Visual
    replacement by overdrawing the intersections and overlaps.  I can't
    see how 3D can look correct without this.

jm  changed screenVectors to mediaVectors.  just a better naming
    convention since it is used with both print and screen media.
In ControlFrame there is a menubar menu... Draw,  things here affect
  only the screen drawing under it you can select,
  - red and blue... basically the code you started with
  - red and blue alternating   ... beginnings of what you need for LCD
  shutter glasses
  - red blue and magenta,  working version of my original code to
  overplot in magenta

I also added a draw Frames/sec option.  I drew it in green which will
probably make it invisible [actually partially visible] with 3-d
glasses.  It is prelude to a slider to control SLEEPFOR. I did some
tests and it will be easy to squeeze the rotate sliders to make room for
a new slider.

In CDrawPanel lots of code to support the 3 drawing modes selectable
from controlframe.

CDrawPanel now obeys the color selection for screen colors made in
Hyper3. I think magenta didn't get done, but its a trivial fix.

Hyper3 found all places where rotate was set, and changed to
setRotate(value).  I needed this so that the red blue only drawing mode
would not stop with just last color showing. I updated the internal date
and put a version of 3.11+.  The version in 3.11 zip file said 3.10 and
had a date in mid June.

Vector2D has new version of overplot code.  As far as I can tell it
correctly handles all cases. Horizontal, vertical and diagonal overlaps
work.  I have also suppressed the drawing of single point intersections.
I did this because it causes noticeable cpu load to include them.  I'm
not sure what the visual effect is to omit these points. Without 3-d
glasses they are invisible.
changed colorPrintMagenta to 0,32,255.  too much green.
changed printing code so that white background's overlap is black
    (colorPrintBlack), and black background's overlap color is
    magenta (colorPrintMagenta).
added comment near colors: left is red, right is blue
updated outdated description in Hyper3.java
optimized Vector2D overlap code for more speed.

Only a small amount of functional change but lots of code refactoring.

There are several new classes,  the most important of these is probably
ColorScheme. A ColorScheme consists of 4 colors,  the left eye, right
eye, overlap to use on black background, and overlap to use on white

The printer code has been pulled out to a class called Printer.

The image out code has been pulled out to a call called ImageWriter.

The code to load images from files has been put in a class called

I was going to create a Listener class but ran out of energy.

lcd shutter code can be included by removing a comment in ControlFrame
and a few more in  CDrawPanel.

There is a enum called DrawType to control the drawing selections...

I have also added  red blue/red green radiobuttons.  I have tested
screen and write codes fairly well, but since I don't own a color
printer  the printer code could be badly broken and I wouldn't know it.

I made alteration mode the default.

I turned down the red intensity for screen mode to 128 because at 256 I
got a tremendous amount of bleed through of red to my right (blue) eye.
I found the floating extra red object very distracting/confusing.  If
this is a problem then a way to select color intensity should be

If you own red-green glasses, you can tweek the red-greed colors...
bottom of ColorScheme.java

One thing I failed to fix was that  when you save a file it should be
put in the directory the chooser is pointing to... and that directory
should be retained as starting point for the next chooser. Currently the
write is always in ".".


printer code for a long time has been making view-upside-down printouts.
the problem seems to be that for printing, some reason left and right
are swapped.  Sorry, I had to tweak what looks like correct code to
correct a real-world anomaly.

set EYESHIFT to 0.  though I have done this, I would prefer to leave
this in the equations for future use. this is an alternate solution the
of the printer problems as well, although the right-left swap is still
the real culprit.

in rotate4D() I included an if (true) statement to  allow switching
between original supposedly incorrect rotation equations/code and the
supposedly correct code.  There may be some sort of rotation convention
involved behind the reason involved for using the strange method that we
did originally, but at this point it is unknown, and I have no math
professor to correct me.

changed window exit code to call caller.drawPanel.close() so serial
ports get closed. as a result of this, had to change "Hyper3 caller"
parameter to final to get it to compile. didn't seem to break anything.
Attached is a working version of Vector2D.java.  The list.size()=3
messages were coming from a "can't happen" section.  Although I still
don't know how it happens ( but is related to at least 1 end being same
) I have a work around.  The only object I was able to invoke the error
was the big hypersphere.  I think my solution is correct.... even though
it simply ignores the extra point, which always seems to match one of
the other points.
lots of changes including much faster rendering

Hyper3.java added variable ZF to fix red blue shift problem.  Original
behavior can be seen by setting ZF=1.0. New code to speed up screen
drawing. Old drawing code still used by Printer and imageWriter.
Modified doWriteImageDialog to use the directory chosen and remember it
for the next save.

CDrawPanel.java rewritten to use new faster code.  Overlap is still done
with the old code. The new code doesn't lend itself to calculating the
overlaps. Some restructuring of logic... seems to work.

Loader.java after reading in an object, the Vector2D ints are recast as
an int[][] objectLines array. These ints represent consecutive lines in
the object.

Printer.java restored right and left colors

ImageWriter.java will create subdirectories  to save files in.  This
came up when I tried to create  images/HCUBE   as text in dialog and
directory "images" did not exist.  A printStackTrace() over 50 lines
long was generated bu sun code.

VPoint.java  new class to pass info back to CDrawPanel from fast code.
Holds both left and right screen  points  for a single  Vertex.

Note: when large images are drawn on my LCD monitor, blinking is seen.
It is reminiscent of things that used to be cured in unix X11 by
synchronizing double buffering with vertical retrace. But nothing like
that seems to exist in java. JPanel is supposed to be double buffered by

disabled new variable ZF by setting to 1.0 because it was affecting

discovered correct rotation matrices.  switched rotation code.
freed up CPU resources by request of sjm (good idea) - added
startRotating() and stopRotating() and changed stop and rotate buttons,
and everything involving the thread "rotator" so that rotate button
starts the thread (when it's not already running) and the stop button
allows the thread to terminate.

added 24-cell.4d and hyperoctahedron.4d and simplex.4d
resizing a window now automatically changes dw so the object doesn't
look weird.

600-cell wikipedia
120-cell wikipedia
16-cell wikipedia
24-cell wikipedia
tesseract wikipedia
pentachoron wikipedia
sudanese moebius band wikipedia (this one mentions the use of R4 (4D) or C2 for the sudanese moebius band.)
collection of Coxeter polytopes & polyhedra and a link to Jenn3D, an OpenGL polytope viewer
use this 3rd-party applet if you can't figure out how to run the Hyper3 program. can't save images or load hyperspheres or other polytopes though.
4D rubik's cube (fun to play with, terrible to solve)

list of 4D objects