diff options
author | Sven Gothel <[email protected]> | 2000-11-18 06:43:49 +0000 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2000-11-18 06:43:49 +0000 |
commit | 880653d31a8f1ff8384fdbc75b84934bceecfdb8 (patch) | |
tree | bdafb71416f176d2a4b73bf716c9dc3f13685a8b /demos/RonsDemos/steam.java |
Initial revision
Diffstat (limited to 'demos/RonsDemos/steam.java')
-rw-r--r-- | demos/RonsDemos/steam.java | 791 |
1 files changed, 791 insertions, 0 deletions
diff --git a/demos/RonsDemos/steam.java b/demos/RonsDemos/steam.java new file mode 100644 index 0000000..3f19f7e --- /dev/null +++ b/demos/RonsDemos/steam.java @@ -0,0 +1,791 @@ +/**
+ * @(#) steam.java
+ * @(#) author: Troy Robinette (converted to Java by Ron Cemer)
+ */
+
+import java.applet.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.lang.*;
+import java.util.*;
+import java.io.*;
+import java.util.*;
+import gl4java.GLContext;
+import gl4java.awt.GLAnimCanvas;
+import gl4java.applet.SimpleGLAnimApplet1;
+
+/**
+ Description: Interactive 3D graphics, Assignment #1
+ Miniature Steam Engine Simulation.
+ Author: Troy Robinette
+ Date: 29/9/95
+ Email: [email protected]
+ Notes: - Transparence doesn't quite work. The color of the
+ underlying object doesn't show through.
+ - Also only the front side of the transparent objects are
+ transparent.
+**/
+
+public class steam extends SimpleGLAnimApplet1
+{
+ private static final float boxnormals[][] =
+ {
+ {-1.0f, 0.0f, 0.0f},
+ {0.0f, 1.0f, 0.0f},
+ {1.0f, 0.0f, 0.0f},
+ {0.0f, -1.0f, 0.0f},
+ {0.0f, 0.0f, 1.0f},
+ {0.0f, 0.0f, -1.0f}
+ };
+ private static final int boxfaces[][] =
+ {
+ {0, 1, 2, 3},
+ {3, 2, 6, 7},
+ {7, 6, 5, 4},
+ {4, 5, 1, 0},
+ {5, 6, 2, 1},
+ {7, 4, 0, 3}
+ };
+
+ /* Initialize the applet */
+
+
+ public void init()
+ {
+ super.init();
+ Dimension d = getSize();
+ canvas = new steamCanvas(d.width, d.height);
+ canvas.requestFocus();
+ add("Center", canvas);
+ }
+
+
+ /* Local GLAnimCanvas extension class */
+
+
+ private class steamCanvas extends GLAnimCanvas
+ implements MouseListener, ActionListener, KeyListener
+ {
+ /* Dimensions of texture image. */
+ private final int IMAGE_WIDTH = 64;
+ private final int IMAGE_HEIGHT = 64;
+ /* Step to be taken for each rotation. */
+ private final int ANGLE_STEP = 10;
+ /* Magic numbers for relationship b/w cylinder head and crankshaft. */
+ private final float MAGNITUDE = 120.0f;
+ private final float PHASE = 270.112f;
+ private final float FREQ_DIV = 58.0f;
+ private final float ARC_LENGTH = 2.7f;
+ private final float ARC_RADIUS = 0.15f;
+ /* Rotation angles */
+ private float view_h = 270.0f, view_v = 0.0f;
+ private float head_angle = 0.0f;
+ private int crank_angle = 0;
+ /* Crank rotation step. */
+ private float crank_step = 5.0f;
+ /* Toggles */
+ private boolean filled = true;
+ private boolean textured = false, transparent = false;
+ /* Storage for the angle look up table and the texture map */
+ private float head_look_up_table[] = new float[360];
+ private byte image[] = new byte[IMAGE_WIDTH*IMAGE_HEIGHT*3];
+ /* Indentifiers for each Display list */
+ private int list_piston_filled = 1;
+ private int list_piston_texture = 2;
+ private int list_flywheel_filled = 4;
+ private int list_flywheel_texture = 8;
+ /* Variable used in the creaton of glu objects */
+ int obj; // (GLU quadric object)
+
+ private PopupMenu menu = null;
+ private boolean menu_showing = false;
+ private boolean save_suspended = false;
+
+ private final String MENU_FILLED = "Filled";
+ private final String MENU_WIREFRAME = "Wireframe";
+ private final String MENU_TEXTURED = "Textured";
+ private final String MENU_UNTEXTURED = "Untextured";
+ private final String MENU_TRANSPARENT = "Transparent";
+ private final String MENU_OPAQUE = "Opaque";
+ private final String MENU_RIGHT_LIGHT_ON = "Right light on";
+ private final String MENU_RIGHT_LIGHT_OFF = "Right light off";
+ private final String MENU_LEFT_LIGHT_ON = "Left light on";
+ private final String MENU_LEFT_LIGHT_OFF = "Left light off";
+ private final String MENU_PAUSE = "Pause (use a and z to step)";
+ private final String MENU_RESUME = "Resume animation";
+ private final String MENU_SPEED_UP = "Speed up (+)";
+ private final String MENU_SLOW_DOWN = "Slow down (-)";
+
+ public steamCanvas(int w, int h)
+ {
+ super(w, h);
+ GLContext.gljNativeDebug = false;
+ GLContext.gljClassDebug = false;
+ setAnimateFps(30.0);
+ }
+
+ public void preInit()
+ {
+ doubleBuffer = true;
+ stereoView = false;
+ }
+
+ public void init()
+ {
+ System.out.println("init(): " + this);
+ reshape(getSize().width, getSize().height);
+
+ float mat_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
+ float mat_shininess[] = {50.0f};
+ float light_position0[] = {1.0f, 1.0f, 1.0f, 0.0f};
+ float light_position1[] = {-1.0f, 1.0f, 1.0f, 0.0f};
+ float light_diffuse1[] = {1.0f,1.0f,1.0f,1.0f};
+ float light_specular1[] = {1.0f,1.0f,1.0f,1.0f};
+
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+ obj = glu.gluNewQuadric();
+ make_table();
+ make_image();
+
+ /* Set up Texturing */
+ gl.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ gl.glTexImage2D
+ (GL_TEXTURE_2D,
+ 0,
+ 3,
+ IMAGE_WIDTH,
+ IMAGE_HEIGHT,
+ 0,
+ GL_RGB,
+ GL_UNSIGNED_BYTE,
+ image);
+ gl.glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ gl.glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ gl.glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ gl.glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ gl.glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+ /* Set up Lighting */
+ gl.glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
+ gl.glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
+ gl.glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
+ gl.glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
+ gl.glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1);
+ gl.glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular1);
+
+ /* Initial render mode is with full shading and LIGHT 0
+ enabled. */
+ gl.glEnable(GL_LIGHTING);
+ gl.glEnable(GL_LIGHT0);
+ gl.glDisable(GL_LIGHT1);
+ gl.glDepthFunc(GL_LEQUAL);
+ gl.glEnable(GL_DEPTH_TEST);
+ gl.glDisable(GL_ALPHA_TEST);
+
+ gl.glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
+ gl.glEnable(GL_COLOR_MATERIAL);
+ gl.glShadeModel(GL_SMOOTH);
+
+ /* Initialise display lists */
+ gl.glNewList(list_piston_filled, GL_COMPILE);
+ draw_piston();
+ gl.glEndList();
+ gl.glNewList(list_flywheel_filled, GL_COMPILE);
+ draw_flywheel();
+ gl.glEndList();
+
+ glu.gluQuadricTexture(obj, true);
+ gl.glNewList(list_piston_texture, GL_COMPILE);
+ draw_piston();
+ gl.glEndList();
+ gl.glNewList(list_flywheel_texture, GL_COMPILE);
+ draw_flywheel();
+ gl.glEndList();
+ glu.gluQuadricTexture(obj, false);
+
+ glj.gljCheckGL();
+
+ menu = new PopupMenu("Options");
+ menu.add(MENU_FILLED);
+ menu.add(MENU_WIREFRAME);
+ menu.add(MENU_TEXTURED);
+ menu.add(MENU_UNTEXTURED);
+ menu.add(MENU_TRANSPARENT);
+ menu.add(MENU_OPAQUE);
+ menu.add(MENU_RIGHT_LIGHT_ON);
+ menu.add(MENU_RIGHT_LIGHT_OFF);
+ menu.add(MENU_LEFT_LIGHT_ON);
+ menu.add(MENU_LEFT_LIGHT_OFF);
+ menu.add(MENU_PAUSE);
+ menu.add(MENU_RESUME);
+ menu.add(MENU_SPEED_UP);
+ menu.add(MENU_SLOW_DOWN);
+ menu.addActionListener(this);
+ add(menu);
+
+ addMouseListener(this);
+ addKeyListener(this);
+ }
+
+ public void doCleanup()
+ {
+ System.out.println("destroy(): " + this);
+ removeMouseListener(this);
+ menu.removeActionListener(this);
+ removeKeyListener(this);
+ }
+
+ public void reshape(int width, int height)
+ {
+ gl.glViewport(0,0,width,height);
+ gl.glMatrixMode(GL_PROJECTION);
+ gl.glLoadIdentity();
+ glu.gluPerspective(65.0f, (float)width/(float)height, 1.0f, 20.0f);
+ gl.glMatrixMode(GL_MODELVIEW);
+ gl.glLoadIdentity();
+ gl.glTranslatef(0.0f, 0.0f, -5.0f); /* viewing transform */
+ gl.glScalef(1.5f, 1.5f, 1.5f);
+ }
+
+ public void display()
+ {
+ if (glj.gljMakeCurrent() == false) return;
+
+ if (!isSuspended())
+ {
+ crank_angle += crank_step;
+ while (crank_angle >= 360) crank_angle -= 360;
+ while (crank_angle < 0) crank_angle += 360;
+ head_angle = head_look_up_table[crank_angle];
+ }
+
+ /* Main display code. Clears the drawing buffer and if
+ transparency is set, displays the model twice, 1st time
+ accepting those fragments with an ALPHA value of 1 only,
+ then with DEPTH_BUFFER writing disabled for those with
+ other values. */
+
+ int pass;
+ gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ gl.glPushMatrix();
+ if (transparent)
+ {
+ gl.glEnable(GL_ALPHA_TEST);
+ pass = 2;
+ }
+ else
+ {
+ gl.glDisable(GL_ALPHA_TEST);
+ pass = 0;
+ }
+
+ /* Rotate the whole model */
+ gl.glRotatef(view_h, 0.0f, 1.0f, 0.0f);
+ gl.glRotatef(view_v, 1.0f, 0.0f, 0.0f);
+
+ do
+ {
+ if (pass == 2)
+ {
+ gl.glAlphaFunc(GL_EQUAL, 1);
+ gl.glDepthMask(true);
+ pass = 1;
+ }
+ else if (pass != 0)
+ {
+ gl.glAlphaFunc(GL_NOTEQUAL, 1);
+ gl.glDepthMask(false);
+ pass = 0;
+ }
+
+ draw_engine_pole();
+
+ gl.glPushMatrix();
+ gl.glTranslatef(0.5f, 1.4f, 0.0f);
+ draw_cylinder_head();
+ gl.glPopMatrix();
+
+ gl.glPushMatrix();
+ gl.glTranslatef(0.0f, -0.8f, 0.0f);
+ draw_crank();
+ gl.glPopMatrix();
+ } while (pass > 0);
+
+ gl.glDepthMask(true);
+ gl.glPopMatrix();
+
+ glj.gljSwap();
+ glj.gljCheckGL();
+ glj.gljFree();
+
+ //if (!isSuspended()) repaint(); // Animate at full speed.
+ }
+
+ // Methods required for the implementation of MouseListener
+ public void mouseEntered( MouseEvent evt )
+ {
+ Component comp = evt.getComponent();
+ if( comp.equals(this ) )
+ {
+ requestFocus();
+ }
+ }
+
+ public void mouseClicked( MouseEvent evt )
+ {
+ Component comp = evt.getComponent();
+ if( comp.equals(this ) )
+ {
+ requestFocus();
+ }
+ }
+
+ public void mouseExited(MouseEvent evt)
+ {
+ }
+
+ public void mousePressed(MouseEvent evt)
+ {
+ // If user presses right mouse button within canvas area,
+ // suspend animation and pop up menu.
+ // If menu was already popped up and user presses either
+ // mouse button within canvas area, resume animation
+ // because the menu will have been removed automatically.
+ if (!menu_showing)
+ {
+ if ((evt.getModifiers() & evt.BUTTON3_MASK) != 0)
+ {
+ menu_showing = true;
+ save_suspended = isSuspended();
+ if (!save_suspended)
+ {
+ setSuspended(true);
+ repaint(100);
+ try
+ {
+ Thread.currentThread().sleep(200);
+ }
+ catch (Exception e)
+ { }
+ }
+ menu.show(this,evt.getX(),evt.getY());
+ }
+ }
+ else
+ {
+ menu_showing = false;
+ setSuspended(save_suspended);
+ }
+ }
+
+ public void mouseReleased(MouseEvent evt)
+ {
+ }
+
+ // Method required for the implementation of ActionListener
+ public void actionPerformed(ActionEvent evt)
+ {
+ if (glj.gljMakeCurrent() == false) return;
+ boolean dorepaint = false;
+ String c = evt.getActionCommand();
+ if (c.equals(MENU_FILLED))
+ {
+ filled = true;
+ gl.glShadeModel(GL_SMOOTH);
+ gl.glEnable(GL_LIGHTING);
+ gl.glEnable(GL_DEPTH_TEST);
+ gl.glEnable(GL_COLOR_MATERIAL);
+ glu.gluQuadricNormals(obj, GLU_SMOOTH);
+ glu.gluQuadricDrawStyle(obj, GLU_FILL);
+ // Conditionally re-enable texturing.
+ if (textured)
+ {
+ gl.glEnable(GL_TEXTURE_2D);
+ glu.gluQuadricTexture(obj, true);
+ }
+ dorepaint = true;
+ }
+ else if (c.equals(MENU_WIREFRAME))
+ {
+ filled = false;
+ gl.glShadeModel(GL_FLAT);
+ gl.glDisable(GL_LIGHTING);
+ gl.glDisable(GL_DEPTH_TEST);
+ gl.glDisable(GL_COLOR_MATERIAL);
+ glu.gluQuadricNormals(obj, GLU_NONE);
+ glu.gluQuadricDrawStyle(obj, GLU_LINE);
+ glu.gluQuadricTexture(obj, false);
+ // Be sure texturing is disabled.
+ gl.glDisable(GL_TEXTURE_2D);
+ glu.gluQuadricTexture(obj, false);
+ dorepaint = true;
+ }
+ else if (c.equals(MENU_TEXTURED))
+ {
+ textured = true;
+ if (filled)
+ {
+ gl.glEnable(GL_TEXTURE_2D);
+ glu.gluQuadricTexture(obj, true);
+ dorepaint = true;
+ }
+ }
+ else if (c.equals(MENU_UNTEXTURED))
+ {
+ textured = false;
+ gl.glDisable(GL_TEXTURE_2D);
+ glu.gluQuadricTexture(obj, false);
+ dorepaint = true;
+ }
+ else if (c.equals(MENU_TRANSPARENT))
+ {
+ transparent = true;
+ dorepaint = true;
+ }
+ else if (c.equals(MENU_OPAQUE))
+ {
+ transparent = false;
+ dorepaint = true;
+ }
+ else if (c.equals(MENU_RIGHT_LIGHT_ON))
+ {
+ gl.glEnable(GL_LIGHT0);
+ dorepaint = true;
+ }
+ else if (c.equals(MENU_RIGHT_LIGHT_OFF))
+ {
+ gl.glDisable(GL_LIGHT0);
+ dorepaint = true;
+ }
+ else if (c.equals(MENU_LEFT_LIGHT_ON))
+ {
+ gl.glEnable(GL_LIGHT1);
+ dorepaint = true;
+ }
+ else if (c.equals(MENU_LEFT_LIGHT_OFF))
+ {
+ gl.glDisable(GL_LIGHT1);
+ dorepaint = true;
+ }
+ else if (c.equals(MENU_PAUSE))
+ {
+ if (menu_showing)
+ save_suspended = true;
+ else
+ setSuspended(true);
+ }
+ else if (c.equals(MENU_RESUME))
+ {
+ if (menu_showing)
+ save_suspended = false;
+ else
+ setSuspended(false);
+ }
+ else if (c.equals(MENU_SPEED_UP))
+ {
+ crank_step++;
+ if (crank_step > 45) crank_step = 45;
+ }
+ else if (c.equals(MENU_SLOW_DOWN))
+ {
+ crank_step--;
+ if (crank_step < 1) crank_step = 1;
+ }
+ if (menu_showing)
+ {
+ menu_showing = false;
+ setSuspended(save_suspended);
+ }
+ glj.gljFree();
+ if (dorepaint) repaint();
+ }
+
+ // Methods required for the implementation of KeyListener
+ public void keyPressed(KeyEvent e)
+ {
+ switch (e.getKeyCode())
+ {
+ case KeyEvent.VK_LEFT:
+ view_h -= ANGLE_STEP;
+ while (view_h < 0) view_h += 360;
+ repaint();
+ break;
+ case KeyEvent.VK_RIGHT:
+ view_h += ANGLE_STEP;
+ while (view_h >= 360) view_h -= 360;
+ repaint();
+ break;
+ case KeyEvent.VK_UP:
+ view_v += ANGLE_STEP;
+ while (view_v >= 360) view_v -= 360;
+ repaint();
+ break;
+ case KeyEvent.VK_DOWN:
+ view_v -= ANGLE_STEP;
+ while (view_v < 0) view_v += 360;
+ repaint();
+ break;
+ }
+ }
+
+ public void keyReleased(KeyEvent e)
+ {
+ }
+
+ public void keyTyped(KeyEvent e)
+ {
+ if (glj.gljMakeCurrent() == false) return;
+ boolean dorepaint = false;
+ switch ((char)e.getKeyChar())
+ {
+ case 'a':
+ case 'A':
+ if (!isSuspended()) break;
+ crank_angle += crank_step;
+ while (crank_angle >= 360) crank_angle -= 360;
+ head_angle = head_look_up_table[crank_angle];
+ dorepaint = true;
+ break;
+ case 'z':
+ case 'Z':
+ if (!isSuspended()) break;
+ crank_angle -= crank_step;
+ while (crank_angle < 0) crank_angle += 360;
+ head_angle = head_look_up_table[crank_angle];
+ dorepaint = true;
+ break;
+ case '+':
+ crank_step++;
+ if (crank_step > 45) crank_step = 45;
+ break;
+ case '-':
+ crank_step--;
+ if (crank_step < 1) crank_step = 1;
+ break;
+ }
+ glj.gljFree();
+ if (dorepaint) repaint();
+ }
+
+ /* Draws a box by scaling a glut cube of size 1.
+ Also checks the filled toggle to see which rendering
+ style to use. NB Texture doesn't work correctly due
+ to the cube being scaled. */
+ private void myBox(float x, float y, float z)
+ {
+ gl.glPushMatrix();
+ gl.glScalef(x, y, z);
+ if (filled)
+ glutSolidCube(1);
+ else
+ glutWireCube(1);
+ gl.glPopMatrix();
+ }
+
+ /* Draws a cylinder using glu function, drawing flat discs
+ at each end, to give the appearence of it being solid. */
+ private void myCylinder
+ (int object, float outerRadius, float innerRadius, float length)
+ {
+ gl.glPushMatrix();
+ glu.gluCylinder(object, outerRadius, outerRadius, length, 20, 1);
+ gl.glPushMatrix();
+ gl.glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
+ glu.gluDisk(object, innerRadius, outerRadius, 20, 1);
+ gl.glPopMatrix();
+ gl.glTranslatef(0.0f, 0.0f, length);
+ glu.gluDisk(object, innerRadius, outerRadius, 20, 1);
+ gl.glPopMatrix();
+ }
+
+ /* Draws a piston. */
+ private void draw_piston()
+ {
+ gl.glPushMatrix();
+ gl.glColor4f(0.3f, 0.6f, 0.9f, 1.0f);
+ gl.glPushMatrix();
+ gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+ gl.glTranslatef(0.0f, 0.0f, -0.07f);
+ myCylinder(obj, 0.125f, 0.06f, 0.12f);
+ gl.glPopMatrix();
+ gl.glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
+ gl.glTranslatef(0.0f, 0.0f, 0.05f);
+ myCylinder(obj, 0.06f, 0.0f, 0.6f);
+ gl.glTranslatef(0.0f, 0.0f, 0.6f);
+ myCylinder(obj, 0.2f, 0.0f, 0.5f);
+ gl.glPopMatrix();
+ }
+
+ /* Draws the engine pole and the
+ pivot pole for the cylinder head. */
+ private void draw_engine_pole()
+ {
+ gl.glPushMatrix();
+ gl.glColor4f(0.9f, 0.9f, 0.9f, 1.0f);
+ myBox(0.5f, 3.0f, 0.5f);
+ gl.glColor3f(0.5f, 0.1f, 0.5f);
+ gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+ gl.glTranslatef(0.0f, 0.9f, -0.4f);
+ myCylinder(obj, 0.1f, 0.0f, 2);
+ gl.glPopMatrix();
+ }
+
+ /* Draws the cylinder head at the appropreate angle, doing
+ the necessary translations for the rotation. */
+ private void draw_cylinder_head()
+ {
+ gl.glPushMatrix();
+ gl.glColor4f(0.5f, 1.0f, 0.5f, 0.1f);
+ gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
+ gl.glTranslatef(0.0f, 0.0f, 0.4f);
+ gl.glRotatef(head_angle, 1.0f, 0.0f, 0.0f);
+ gl.glTranslatef(0.0f, 0.0f, -0.4f);
+ myCylinder(obj, 0.23f, 0.21f, 1.6f);
+ gl.glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
+ glu.gluDisk(obj, 0.0f, 0.23f, 20, 1);
+ gl.glPopMatrix();
+ }
+
+ /* Draws the flywheel. */
+ private void draw_flywheel()
+ {
+ gl.glPushMatrix();
+ gl.glColor4f(0.5f, 0.5f, 1.0f, 1.0f);
+ gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+ myCylinder(obj, 0.625f, 0.08f, 0.5f);
+ gl.glPopMatrix();
+ }
+
+/* Draws the crank bell, and the pivot pin for the piston. Also calls the
+ appropreate display list of a piston doing the nesacary rotations before
+ hand. */
+ private void draw_crankbell()
+ {
+ gl.glPushMatrix();
+ gl.glColor4f(1.0f, 0.5f, 0.5f, 1.0f);
+ gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+ myCylinder(obj, 0.3f, 0.08f, 0.12f);
+
+ gl.glColor4f(0.5f, 0.1f, 0.5f, 1.0f);
+ gl.glTranslatef(0.0f, 0.2f, 0.0f);
+ myCylinder(obj, 0.06f, 0.0f, 0.34f);
+
+ gl.glTranslatef(0.0f, 0.0f, 0.22f);
+ gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+ gl.glRotatef(((float)crank_angle)-head_angle, 1.0f, 0.0f, 0.0f);
+ if (filled)
+ {
+ if (textured)
+ gl.glCallList(list_piston_texture);
+ else
+ gl.glCallList(list_piston_filled);
+ }
+ else
+ draw_piston();
+ gl.glPopMatrix();
+ }
+
+ /* Draws the complete crank. Piston also gets drawn through
+ the crank bell function. */
+ private void draw_crank()
+ {
+ gl.glPushMatrix();
+ gl.glRotatef(crank_angle, 1.0f, 0.0f, 0.0f);
+
+ gl.glPushMatrix();
+ gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+ gl.glTranslatef(0.0f, 0.0f, -1.0f);
+ myCylinder(obj, 0.08f, 0.0f, 1.4f);
+ gl.glPopMatrix();
+
+ gl.glPushMatrix();
+ gl.glTranslatef(0.28f, 0.0f, 0.0f);
+ draw_crankbell();
+ gl.glPopMatrix();
+
+ gl.glPushMatrix();
+ gl.glTranslatef(-0.77f, 0.0f, 0.0f);
+ if (filled)
+ {
+ if (textured)
+ gl.glCallList(list_flywheel_texture);
+ else
+ gl.glCallList(list_flywheel_filled);
+ }
+ else
+ draw_flywheel();
+ gl.glPopMatrix();
+ gl.glPopMatrix();
+ }
+
+ /* Makes a simple checkered pattern image. (Copied from the
+ redbook example "checker.c".) */
+ private void make_image()
+ {
+ int c, idx = 0;
+ for (int i = 0; i < IMAGE_WIDTH; i++)
+ {
+ for (int j = 0; j < IMAGE_HEIGHT; j++)
+ {
+ c = ((((i & 0x8) == 0) ^ ((j & 0x8)) == 0)) ? 255 : 0;
+ image[idx++] = (byte)c;
+ image[idx++] = (byte)c;
+ image[idx++] = (byte)c;
+ }
+ }
+ }
+
+ /* Makes the head lookup table for all possible crank angles. */
+ private void make_table()
+ {
+ for (int i = 0; i < 360; i++)
+ {
+ float rads = PHASE-(((float)i)/FREQ_DIV);
+ head_look_up_table[i] =
+ MAGNITUDE *
+ (float)Math.atan
+ ((ARC_RADIUS*Math.sin(rads)) /
+ (ARC_LENGTH-(ARC_RADIUS*Math.cos(rads))));
+ }
+ }
+
+ // Imported from glut.
+ private void glutWireCube(float size)
+ {
+ drawBox(size, GL_LINE_LOOP);
+ }
+
+ // Imported from glut.
+ private void glutSolidCube(float size)
+ {
+ drawBox(size, GL_QUADS);
+ }
+
+ // Imported from glut.
+ private void drawBox(float size, int type)
+ {
+ float v[][] = new float[8][3];
+ int i;
+
+ v[0][0] = v[1][0] = v[2][0] = v[3][0] = -size / 2;
+ v[4][0] = v[5][0] = v[6][0] = v[7][0] = size / 2;
+ v[0][1] = v[1][1] = v[4][1] = v[5][1] = -size / 2;
+ v[2][1] = v[3][1] = v[6][1] = v[7][1] = size / 2;
+ v[0][2] = v[3][2] = v[4][2] = v[7][2] = -size / 2;
+ v[1][2] = v[2][2] = v[5][2] = v[6][2] = size / 2;
+
+ for (i = 5; i >= 0; i--)
+ {
+ gl.glBegin(type);
+ gl.glNormal3fv(boxnormals[i]);
+ gl.glVertex3fv(v[boxfaces[i][0]]);
+ gl.glVertex3fv(v[boxfaces[i][1]]);
+ gl.glVertex3fv(v[boxfaces[i][2]]);
+ gl.glVertex3fv(v[boxfaces[i][3]]);
+ gl.glEnd();
+ }
+ }
+ }
+}
|