summaryrefslogtreecommitdiff
path: root/src/Robot.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/Robot.java')
-rw-r--r--src/Robot.java285
1 files changed, 285 insertions, 0 deletions
diff --git a/src/Robot.java b/src/Robot.java
new file mode 100644
index 0000000..ca2622b
--- /dev/null
+++ b/src/Robot.java
@@ -0,0 +1,285 @@
+
+import java.awt.Color;
+import javax.media.opengl.GL;
+import static javax.media.opengl.GL2.*;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+
+/**
+ * Represents a Robot, to be implemented according to the Assignments.
+ */
+class Robot extends BetterBase {
+ 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;
+ private final float torsoWidth;
+ private final float shoulderRadius;
+ private final float armLength;
+ private final float legLength;
+ private final float armWidth;
+ private final float legWidth;
+ private final float neckHeight;
+ private final float headRadius;
+ private final float depth;
+ private final float footWidth;
+ private final float footHeight;
+ private final float 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.
+ */
+ public Robot(Material material) {
+ /* Set all parameters of the robot */
+ this.material = material;
+ this.torsoHeight = 0.6f;
+ this.torsoWidth = 0.48f;
+ this.shoulderRadius = 0.09f;
+ this.armLength = 0.6f;
+ this.armWidth = 0.06f;
+ this.legLength = 0.78f;
+ 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;
+ }
+
+ /**
+ * 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);
+
+ // 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 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 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 joint for stick figure model.
+ */
+ private void drawJoint() {
+ if (asStickFigure) {
+ glut.glutSolidSphere(boneSize * 1.5, 10, 10);
+ }
+ }
+
+ /**
+ * Draws the torso of the robot.
+ */
+ private void drawTorso() {
+ // Scale the torso to specified values
+ 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 drawShoulderTop() {
+ // save position
+ gl.glPushMatrix();
+
+ 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
+ glut.glutSolidSphere(shoulderRadius, 10, 10);
+ // left shoulder
+ gl.glTranslatef(-2 * shoulder_x, 0, 0);
+ glut.glutSolidSphere(shoulderRadius, 10, 10);
+
+ // restore position
+ gl.glPopMatrix();
+ }
+
+ /**
+ * 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 drawLeg(boolean isRight) {
+ // save center position
+ gl.glPushMatrix();
+
+ // 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 drawArm(boolean isRight) {
+ // Push the translation matrix so we can return to the origin
+ gl.glPushMatrix();
+
+ // 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();
+ }
+
+ /**
+ * Draw the head and the neck of the robot.
+ */
+ private void drawHead() {
+ // Push matrix so we can go to the origin afterwards
+ gl.glPushMatrix();
+
+ // position centered above the torso for the neck
+ gl.glTranslatef(0f, 0f, torsoHeight / 2 + neckHeight / 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
+ setColor(asStickFigure ? boneColor : Colors.PALE_TURQOISE);
+ glut.glutSolidSphere(headRadius, 10, 10);
+
+ // Pop so we are at the origin again
+ gl.glPopMatrix();
+ }
+
+}