diff options
Diffstat (limited to 'src/Robot.java')
-rw-r--r-- | src/Robot.java | 285 |
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(); + } + +} |