CS 151: Lab #11

Lab Exercise 11: 3D Turtle

Main course page

The purpose of this lab is to give you one more chance to extend your drawing system. You should have a reasonable understanding of how all the pieces fit together, so now we're going to swap out the standard 2D turtle and put in a 3D turtle. All of your 2D turtle programs should continue to work just fine, but now you can make 3D shapes as well. In addition, you'll be able to rotate your completed drawings with the mouse.


Tasks

The lab consists of three parts.

The goal is to be able to make 3D shapes and scenes as easily as 2D. You should be able to create a Cube class, for example, as well as 3D trees and other L-system shapes that work exactly the same way as their 2D counterparts.

  1. Create a new working folder. Copy your lsystem.py, interpreter.py, shape.py, and tree.py files from last week. Label them as version 5. Then download the 3D turtle file.
  2. One difference between the standard turtle and the 3D turtle is that the latter is implemented as a class. Therefore, you need to create a single instance of the turtle object that will be used by all Interpreer objects.

    At the top of interpreter.py, create a global variable called turtle and initialize it to None.

    Second, if you have a call to turtle.setup(), delete it.

    Third, before calling any other turtle functions in your __init__ method, but after the test of Interpreter.initialized, put the following two lines.

    global turtle
    turtle = turtleTk3D.Turtle3D(dx, dy)
    

    The first line tells the function to use the turtle variable in the global symbol table, and the second line creates a new turtleTk3D object. By putting the 3D turtle object in a variable called turtle, expressions like turtle.left(angle) or turtle.forward(distance) still work as expected.

  3. Make the following additional changes to interpreter.py.
    • Edit your hold method so that it calls only turtle.mainloop().
    • If you have a goto method, add an optional parameter z with a default value of 0. Then change the turtle.goto call to include z as the third argument.
    • Do the same with the place method. It should have two required arguments (x and y) and two optional arguments (z and orientation).
    • Create additional methods called roll, pitch, and yaw, that call the 3D turtle functions roll, pitch and yaw. These functions will look like your existing orient function.
    • The turtle.position() method now returns the tuple (x, y, z) instead of just (x, y). There are likely some places in your Interpreter's forward method that need to be updated to handle the z coordinate. In the jitter case, you probably want to add a random offset in z, in addition to x and y.
    • Add cases in your drawString method for pitch ( & and ^ ) and roll (\ and /). The & symbol means to execute the pitch method with a positive angle, and ^ should execute the pitch method with a negative angle. The backslash '\' should execute the roll with a positive angle, and the forward slash '/' should execute roll with a negative angle.

      Yaw is still + and -.

    • Note that you will have to use the string '\\' to represent the backward slash character because it is a special character (e.g., '\n' is a newline and '\t' is a tab) .

    • The 3D turtle color function works slightly differently from the regular turtle. The primary difference is that it takes as input r, g, b values, a color string, or a single tuple (r, g, b) and it returns only a single color value. The following sequence still works just fine, and should be the way you work with colors in your drawString cases like leaves and berries.
      oldcolor = turtle.color()
      turtle.color( (0.5, 0.3, 0.8) )
      
      # draw some stuff
      
      turtle.color(oldcolor)
      
  4. Make the following changes to shape.py.

    • Add three optional fields to the Shape class draw function. The arguments should be called roll, pitch, and zpos. Given them all default values of 0. The orientation parameter already holds the yaw information.
    • Add zpos to the place call before drawString.
    • After you have set the orientation using either the place or orient method of the Interpreter object, call the roll method and then the pitch method with the appropriate arguments.
  5. Run the test file basicscene.py. It is a simple example of how to begin building a 3D scene.
  6. Update your tree.py file. Add roll, pitch, and zpos to the parameter list of the draw method, giving them all default values of 0. Then pass the three parameters on to the parent draw function. Then run the test file treescene.py using the L-system systemZ.

Once you have finished the lab, go ahead and get started on project 11.


Appendix: Turtle3D Documentation

The Turtle3D class implements a 3D turtle abstraction using the Tkinter package.

The Turtle3D class includes the following methods for public use.