summaryrefslogtreecommitdiff
path: root/src/RobotRace.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/RobotRace.java')
-rw-r--r--src/RobotRace.java482
1 files changed, 197 insertions, 285 deletions
diff --git a/src/RobotRace.java b/src/RobotRace.java
index b1bf83a..d715a78 100644
--- a/src/RobotRace.java
+++ b/src/RobotRace.java
@@ -1,4 +1,5 @@
+import java.awt.Color;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
@@ -136,7 +137,7 @@ public class RobotRace extends Base {
gl.glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
gl.glBindTexture(GL_TEXTURE_2D, 0);
}
-
+
/**
* Configures the viewing transform.
*/
@@ -228,11 +229,11 @@ public class RobotRace extends Base {
* @param g Green color scale (0 to 1).
* @param b Blue color scale (0 to 1).
*/
- private void drawColoredArrow(float r, float g, float b) {
+ private void drawColoredArrow(Color color) {
gl.glPushMatrix();
// change color
- gl.glColor3f(r, g, b);
+ setColor(color);
// draw a thin line from the origin to the right.
gl.glTranslatef(0.5f, 0, 0);
@@ -258,16 +259,16 @@ public class RobotRace extends Base {
*/
public void drawAxisFrame() {
// X-axis: normal orientation
- drawColoredArrow(1, 0, 0);
+ drawColoredArrow(Color.RED);
// Y-axis: rotate 90 degree clockwise in the Z-axis
gl.glRotatef(90, 0, 0, 1);
- drawColoredArrow(0, 1, 0);
+ drawColoredArrow(Color.GREEN);
gl.glRotatef(-90, 0, 0, 1);
// Z-axis: rotate 90 degree in the XY ais
gl.glRotatef(-90, 0, 1, 0);
- drawColoredArrow(0, 0, 1);
+ drawColoredArrow(Color.BLUE);
gl.glRotatef(90, 0, 1, 0);
// yellow sphere of 0.03m (with ten divisions)
@@ -329,18 +330,38 @@ public class RobotRace extends Base {
this.specular = specular;
}
}
-
+
+ /**
+ * Utility method to set color.
+ * @param color An AWT color.
+ */
+ private void setColor(Color color) {
+ // contains four RGBA color components (floats in range 0 to 1)
+ float[] rgba = color.getRGBComponents(null);
+ gl.glColor3fv(rgba, 0);
+ }
+
/**
* Represents a Robot, to be implemented according to the Assignments.
*/
private class Robot {
-
+ private final Color boneColor = Colors.CHOCOLATE;
+
/** The material from which this robot is built. */
private final Material material;
/** Relative lengths, widths and heights of robot model. */
private final float torsoHeight, torsoWidth, shoulderRadius, armLength,
- legLength, armWidth, legWidth, neckHeight, headRadius, depth;
+ legLength, armWidth, legWidth, neckHeight, headRadius, depth,
+ footWidth, footHeight, footLength;
+
+ /** Size of the bone for stick figures. */
+ private final float boneSize;
+
+ /**
+ * True if a skeleton should be drawn instead of a full body.
+ */
+ private boolean asStickFigure;
/**
* Constructs the robot with initial parameters.
@@ -357,6 +378,10 @@ public class RobotRace extends Base {
this.legWidth = 0.06f;
this.neckHeight = 0.15f;
this.headRadius = 0.12f;
+ this.footWidth = legWidth;
+ this.footHeight = legWidth;
+ this.footLength = 2 * legWidth;
+ this.boneSize = 0.02f;
this.depth = 0.24f;
}
@@ -364,336 +389,223 @@ public class RobotRace extends Base {
* Draws this robot (as a {@code stickfigure} if specified).
*/
public void draw(boolean stickFigure) {
+ this.asStickFigure = stickFigure;
// as the components are drawn with the torso as center, move it up
gl.glPushMatrix();
gl.glTranslatef(0, 0, torsoHeight / 2 + legLength);
- if (!stickFigure) {
- // Draw the robot
- drawTorso(); // Torso
- drawShoulders(); // Shoulders
- drawLegs(); // Legs and feet
- drawArms(); // Arms and hands
- drawHead(); // Neck and head
- } else {
- // Draw the stick figure
- drawStickFigure();
+ // These materials control the reflected light
+ gl.glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material.diffuse, 0);
+ gl.glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material.specular, 0);
+
+ gl.glTranslatef(0, 0, footHeight);
+
+ // Draw the robot, everything is relative to the center of torso.
+ // Static parts:
+ drawTorso();
+ drawHead();
+ // only draw the circles in normal, full body mode
+ if (!asStickFigure) {
+ drawShoulderTop();
}
+ // Parts that should be animated:
+ // draw left and right legs
+ drawLeg(false);
+ drawLeg(true);
+ // draw left and right arms
+ drawArm(false);
+ drawArm(true);
+
// restore position
gl.glPopMatrix();
}
-
+
/**
- * Draws the stickfigure of the robot.
+ * Draws a 3d figure with given dimensions and color. If a stick figure
+ * must be drawn, then the figure will become a thin line in the X, Y
+ * or Z direction depending on the direction parameter.
+ * @param dir Direction of the line segment, relevant for stick figures.
+ * @param color If non-null, it becomes the color for this beam. Ignored
+ * when drawing a stick figure, in that case the boneColor constant will
+ * be used.
*/
- private void drawStickFigure() {
- // Create all vectors based on the real position and the
- // translations of the real robot.
- Vector torsoLeftTop = new Vector(torsoWidth /2, 0f, torsoHeight /2);
- Vector torsoRightTop = new Vector(-torsoWidth/2, 0f, torsoHeight/2);
- Vector torsoLeftBottom = new Vector(torsoWidth / 2, 0f,
- -torsoHeight /2);
- Vector torsoRightBottom = new Vector(-torsoWidth /2 , 0f,
- -torsoHeight /2);
-
- Vector leftShoulder = new Vector(torsoWidth / 2 + armWidth * 1.5f,
- 0f, torsoHeight / 2 - 0.05f);
- Vector rightShoulder = new Vector(-torsoWidth / 2 - armWidth * 1.5f,
- 0f, torsoHeight / 2 - 0.05f);
-
- Vector leftHand = new Vector(torsoWidth / 2 + armWidth * 1.5f,
- 0f, torsoHeight / 2 - 0.05f - armLength);
- Vector rightHand = new Vector(-torsoWidth / 2 - armWidth * 1.5f,
- 0f, torsoHeight / 2 - 0.05f - armLength);
-
- Vector neckStart = new Vector(0f, 0f, torsoHeight/2);
- Vector neckEnd = new Vector(0f, 0f, torsoHeight/2 + neckHeight);
-
- Vector leftLegTop = new Vector(torsoWidth / 2 - legWidth * 2, 0f,
- -torsoHeight / 2);
- Vector leftLegBottom = new Vector(torsoWidth / 2 - legWidth * 2,
- 0f, -torsoHeight / 2 - legLength);
-
- Vector rightLegTop = new Vector(-torsoWidth / 2 + legWidth * 2, 0f,
- -torsoHeight / 2);
- Vector rightLegBottom = new Vector(-torsoWidth / 2 + legWidth * 2,
- 0f, -torsoHeight / 2 - legLength);
-
- /*
- * For future, translate all vectors so they are positioned
- * correctly and that they are rotated correctly.
- *
- * Arms and feet should be translated afterwards to represent
- * the angle to simulate movement.
- */
-
- // Set the color to black
- setColorRGB(0, 0, 0);
-
- // Connect all torso points with a line stip
- gl.glBegin(GL_LINE_STRIP);
- stickPoint(torsoLeftTop);
- stickPoint(torsoRightTop);
- stickPoint(torsoRightBottom);
- stickPoint(torsoLeftBottom);
- stickPoint(torsoLeftTop);
- gl.glEnd();
-
- // Draw head lines based on neck start and end
- gl.glBegin(GL_LINES);
- stickPoint(neckStart);
- stickPoint(neckEnd);
- gl.glEnd();
-
- // Draw arm and leg lines, and connect arms with torso (shoulders)
- gl.glBegin(GL_LINES);
- stickPoint(leftLegTop);
- stickPoint(leftLegBottom);
- stickPoint(rightLegTop);
- stickPoint(rightLegBottom);
- stickPoint(leftShoulder);
- stickPoint(leftHand);
- stickPoint(rightShoulder);
- stickPoint(rightHand);
- stickPoint(rightShoulder);
- stickPoint(torsoRightTop);
- stickPoint(leftShoulder);
- stickPoint(torsoLeftTop);
- gl.glEnd();
-
- // Set point size of the stickfigure
- gl.glPointSize(7.5f);
-
- // Begin drawing all points
- gl.glBegin(GL_POINTS);
-
- // First the torso points
- stickPoint(torsoLeftTop);
- stickPoint(torsoRightTop);
- stickPoint(torsoRightBottom);
- stickPoint(torsoLeftBottom);
-
- // Shoulders and the hands
- stickPoint(leftShoulder);
- stickPoint(rightShoulder);
- stickPoint(leftHand);
- stickPoint(rightHand);
-
- // The neck
- stickPoint(neckStart);
- stickPoint(neckEnd);
-
- // And finally the legs
- stickPoint(leftLegTop);
- stickPoint(leftLegBottom);
- stickPoint(rightLegTop);
- stickPoint(rightLegBottom);
-
- // Stop drawing points
- gl.glEnd();
+ private void drawBeam(float x, float y, float z, Direction dir, Color color) {
+ if (asStickFigure) {
+ // for a stick figure, draw a thin figure without colors
+ switch (dir) {
+ case X:
+ assert x != 0;
+ y = z = boneSize;
+ break;
+ case Y:
+ assert y != 0;
+ x = z = boneSize;
+ break;
+ case Z:
+ assert z != 0;
+ x = y = boneSize;
+ break;
+ default:
+ throw new AssertionError(dir.name());
+ }
+ // stick figures always get a "bone" color
+ setColor(boneColor);
+ } else {
+ assert x != 0;
+ assert y != 0;
+ assert z != 0;
+ if (color != null) {
+ setColor(color);
+ }
+ }
+ gl.glScalef(x, y, z);
+ glut.glutSolidCube(1);
+ // return to previous scales
+ gl.glScalef(1 / x, 1 / y, 1 / z);
}
-
+
/**
- * Draws a point with a given vector p
- * @param p Point in space
+ * Draws a joint for stick figure model.
*/
- private void stickPoint(Vector p) {
- gl.glVertex3f((float) p.x(), (float) p.y(), (float) p.z());
+ private void drawJoint() {
+ if (asStickFigure) {
+ glut.glutSolidSphere(boneSize * 1.5, 10, 10);
+ }
}
-
-
+
/**
* Draws the torso of the robot.
*/
private void drawTorso() {
- // Push matrix for returning to origin later
- gl.glPushMatrix();
-
// Scale the torso to specified values
- gl.glScalef(torsoWidth, depth, torsoHeight);
-
- // Draw the torso itself with given color
- setColorRGB(230, 230, 230);
- glut.glutSolidCube(1f);
-
- // Pop matrix so we return to the origin
- gl.glPopMatrix();
+ drawBeam(torsoWidth, depth, torsoHeight, Direction.Z, Color.LIGHT_GRAY);
+
+ if (asStickFigure) {
+ // draw the bone connecting the arms (visible for stick figure)
+ gl.glTranslatef(0, 0, torsoHeight / 2);
+ drawBeam(torsoWidth + armWidth * 3, boneSize, boneSize, Direction.X, null);
+
+ gl.glTranslatef(0, 0, -torsoHeight);
+ // draw the bone connecting the legs (visible for stick figure)
+ drawBeam(.5f * torsoWidth + legWidth / 2, boneSize, boneSize, Direction.X, null);
+
+ // return to torso center
+ gl.glTranslatef(0, 0, torsoHeight / 2);
+ }
}
/**
* Draws both shoulders of the robot.
*/
- private void drawShoulders() {
- // Push the translation matrix so we can return to the origin
+ private void drawShoulderTop() {
+ // save position
gl.glPushMatrix();
-
- // Translate to the left of the robot for left shoulder
- gl.glTranslatef(torsoWidth / 2 + shoulderRadius / 1.5f, 0f,
- torsoHeight / 2);
-
- // Set the drawing color and draw left shoulder
- setColorRGB(100, 130, 255);
- glut.glutSolidSphere(shoulderRadius, 10, 10);
-
- // Pop the matrix and then push it, so we are at the origin
- gl.glPopMatrix();
- gl.glPushMatrix();
-
- // Translate to the right of the robot for right shoulder
- gl.glTranslatef(- torsoWidth / 2 - shoulderRadius / 1.5f, 0f,
- torsoHeight / 2);
-
+
+ float shoulder_x = torsoWidth / 2 + shoulderRadius / 1.5f;
+ // Translate to the left of the robot for left shoulder
+ gl.glTranslatef(shoulder_x, 0f, torsoHeight / 2);
+
+ setColor(Colors.BLUEISH);
+
// Set the drawing color and draw right shoulder
- setColorRGB(100, 130, 255);
glut.glutSolidSphere(shoulderRadius, 10, 10);
-
- // Pop the translation matrix so we are at the origin
+ // left shoulder
+ gl.glTranslatef(-2 * shoulder_x, 0, 0);
+ glut.glutSolidSphere(shoulderRadius, 10, 10);
+
+ // restore position
gl.glPopMatrix();
}
/**
- * Draws the legs and feet of the robot.
+ * Draws the upper and lower legs and feet of the robot.
+ * @param isRight True if at the robot's right (from the robot POV).
*/
- private void drawLegs() {
- // Push the matrix for returning to origin
+ private void drawLeg(boolean isRight) {
+ // save center position
gl.glPushMatrix();
-
- // Translate and scale for the left leg
- gl.glTranslatef(torsoWidth / 2 - legWidth * 2, 0f,
- - legLength / 2 - torsoHeight / 2);
- gl.glScalef(legWidth, legWidth, legLength);
-
- // Set the color and draw the left leg
- setColorRGB(150, 150, 150);
- glut.glutSolidCube(1f);
-
- // First scale and translate back,
- // then new transformation for left foot
- gl.glScalef(1/legWidth, 1/legWidth, 1/legLength);
- gl.glTranslatef(0f, 0f, - legLength / 2);
- gl.glTranslatef(0f, legWidth / 2, -legWidth / 2);
- gl.glScalef(legWidth, legWidth * 2, legWidth);
-
- // Set the color and draw left foot
- setColorRGB(100, 100, 100);
- glut.glutSolidCube(1f);
-
- // Pop the matrix and then push, so we are at the origin
- gl.glPopMatrix();
- gl.glPushMatrix();
-
- // Translate and scale for the right leg
- gl.glTranslatef(-torsoWidth / 2 + legWidth * 2, 0f,
- - legLength / 2 - torsoHeight / 2);
- gl.glScalef(legWidth, legWidth, legLength);
-
- // Set the color and draw right leg
- setColorRGB(150, 150, 150);
- glut.glutSolidCube(1f);
-
- // Scale and translate back,
- // then translate and scale for right foot
- gl.glScalef(1/legWidth, 1/legWidth, 1/legLength);
- gl.glTranslatef(0f, 0f, - legLength / 2);
- gl.glTranslatef(0f, legWidth / 2, -legWidth / 2);
- gl.glScalef(legWidth, legWidth * 2, legWidth);
-
- // Set color and draw right foot
- setColorRGB(100, 100, 100);
- glut.glutSolidCube(1f);
-
- // Pop so we are at the origin
+
+ // The legs are located on the first and third quarter
+ float leg_top_x = -torsoWidth / 4;
+ if (!isRight) {
+ leg_top_x += torsoWidth / 2;
+ }
+ gl.glTranslatef(leg_top_x, 0f, -torsoHeight / 2);
+ drawJoint();
+
+ // upper leg half
+ gl.glTranslatef(0, 0, -legLength / 4);
+ drawBeam(legWidth, legWidth, legLength / 2, Direction.Z, Color.DARK_GRAY);
+
+ // knee
+ gl.glTranslatef(0, 0, -legLength / 4);
+ drawJoint();
+
+ // lower leg half
+ gl.glTranslatef(0, 0, -legLength / 4);
+ drawBeam(legWidth, legWidth, legLength / 2, Direction.Z, Color.DARK_GRAY);
+
+ // draw feet!
+ if (!asStickFigure) {
+ gl.glTranslatef(0, legWidth / 2, -legLength / 4 - footHeight / 2);
+ drawBeam(footWidth, footLength, footHeight, Direction.Y, Colors.GRAYISH);
+ }
+
+ // Restore position
gl.glPopMatrix();
}
/**
* Draw both arms and both hands of the robot.
+ * @param isRight True if at the robot's right (from the robot POV).
*/
- private void drawArms() {
+ private void drawArm(boolean isRight) {
// Push the translation matrix so we can return to the origin
gl.glPushMatrix();
-
- // Translate and scale for the left arm
- gl.glTranslatef(torsoWidth / 2 + armWidth * 1.5f, 0f,
- torsoHeight / 2 - armLength / 2 - 0.05f);
- gl.glScalef(armWidth, armWidth, armLength);
-
- // Set the color and draw the arm itself
- setColorRGB(200, 200, 200);
- glut.glutSolidCube(1f);
-
- // Translate and scale for the left hand
- gl.glScalef(1/armWidth, 1/armWidth, 1/armLength);
- gl.glTranslatef(0f, 0f, - armLength / 2);
-
- // Set the color and draw the left hand
- setColorRGB(130, 158, 174);
- glut.glutSolidSphere(armWidth * 1.25f, 10, 10);
-
- // Pop the translation matrix and return to the origin
- gl.glPopMatrix();
- gl.glPushMatrix();
-
- // Translate and scale for the right arm
- gl.glTranslatef(-(torsoWidth / 2 + armWidth * 1.5f), 0f,
- torsoHeight / 2 - armLength / 2 - 0.05f);
- gl.glScalef(armWidth, armWidth, armLength);
-
- // Set the color and draw the right arm
- setColorRGB(200, 200, 200);
- glut.glutSolidCube(1f);
-
- // Translate and scale for right hand
- gl.glScalef(1/armWidth, 1/armWidth, 1/armLength);
- gl.glTranslatef(0f, 0f, - armLength / 2);
-
- // Set color and draw the right hand
- setColorRGB(130, 158, 174);
- glut.glutSolidSphere(armWidth * 1.25f, 10, 10);
-
- // Pop the translation matrix so we are at the origin again
+
+ // the arm is located outside the torso
+ float arm_x = torsoWidth / 2 + armWidth * 1.5f;
+ if (isRight) {
+ arm_x *= -1;
+ }
+ // arm starts next to the shoulder let's add a joint there...
+ gl.glTranslatef(arm_x, 0, torsoHeight / 2);
+ drawJoint();
+
+ // here is your arm (start drawing from the elbow)
+ gl.glTranslatef(0, 0, - armLength / 2);
+ drawBeam(armWidth, armWidth, armLength, Direction.Z, Colors.ARM_GRAY_COLOR);
+
+ if (!asStickFigure) {
+ // Give me a big hand!
+ setColor(Colors.DIRTY_BLUE);
+ gl.glTranslatef(0f, 0f, - armLength / 2);
+ glut.glutSolidSphere(armWidth * 1.25f, 10, 10);
+ }
+
gl.glPopMatrix();
}
/**
- * Set the color for drawing specified with RGB values.
- *
- * @param r Red parameter (0 - 255)
- * @param g Green parameter (0 - 255)
- * @param b Blue parameter (0 - 255)
- */
- private void setColorRGB(int r, int g, int b) {
- gl.glColor3ub((byte) r, (byte) g, (byte) b);
- }
-
- /**
* Draw the head and the neck of the robot.
*/
private void drawHead() {
// Push matrix so we can go to the origin afterwards
gl.glPushMatrix();
-
- // Translate and scale for the neck
+
+ // position centered above the torso for the neck
gl.glTranslatef(0f, 0f, torsoHeight / 2 + neckHeight / 2);
- gl.glScalef(headRadius / 2.5f, headRadius / 2.5f, neckHeight);
-
- // Set color and draw neck
- setColorRGB(230, 230, 230);
- glut.glutSolidCube(1f);
-
- // Pop the matrix and push so we are at the origin again
- gl.glPopMatrix();
- gl.glPushMatrix();
-
- // Translate so we are above the neck for the head
- gl.glTranslatef(0f, 0f, torsoHeight / 2 + neckHeight
- + headRadius / 2);
-
+ float neckRadius = headRadius / 2.5f;
+ drawBeam(neckRadius, neckRadius, neckHeight, Direction.Z, Colors.LAVENDER);
+
+ // continue moving to the center of the head
+ gl.glTranslatef(0f, 0f, neckHeight / 2 + headRadius / 2);
+
// Set color and draw head
- setColorRGB(190, 210, 220);
+ setColor(asStickFigure ? boneColor : Colors.PALE_TURQOISE);
glut.glutSolidSphere(headRadius, 10, 10);
-
+
// Pop so we are at the origin again
gl.glPopMatrix();
}